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

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 (472) hide show
  1. package/dist/actions/action-events.d.ts +67 -0
  2. package/dist/actions/action-events.d.ts.map +1 -0
  3. package/dist/actions/action-events.js +164 -0
  4. package/dist/actions/action-events.js.map +1 -0
  5. package/dist/actions/close-position/close-position.action.d.ts +1 -1
  6. package/dist/actions/close-position/close-position.action.d.ts.map +1 -1
  7. package/dist/actions/close-position/close-position.action.js +108 -86
  8. package/dist/actions/close-position/close-position.action.js.map +1 -1
  9. package/dist/actions/decision-engine.d.ts.map +1 -1
  10. package/dist/actions/decision-engine.js +40 -28
  11. package/dist/actions/decision-engine.js.map +1 -1
  12. package/dist/actions/event-derivation.d.ts +61 -0
  13. package/dist/actions/event-derivation.d.ts.map +1 -0
  14. package/dist/actions/event-derivation.js +180 -0
  15. package/dist/actions/event-derivation.js.map +1 -0
  16. package/dist/actions/llm-decision/anthropic-llm-decision.d.ts +5 -9
  17. package/dist/actions/llm-decision/anthropic-llm-decision.d.ts.map +1 -1
  18. package/dist/actions/llm-decision/anthropic-llm-decision.js +6 -87
  19. package/dist/actions/llm-decision/anthropic-llm-decision.js.map +1 -1
  20. package/dist/actions/llm-decision/factory.d.ts +0 -6
  21. package/dist/actions/llm-decision/factory.d.ts.map +1 -1
  22. package/dist/actions/llm-decision/factory.js +0 -2
  23. package/dist/actions/llm-decision/factory.js.map +1 -1
  24. package/dist/actions/llm-decision/openclaw-llm-decision.d.ts.map +1 -1
  25. package/dist/actions/llm-decision/openclaw-llm-decision.js +26 -7
  26. package/dist/actions/llm-decision/openclaw-llm-decision.js.map +1 -1
  27. package/dist/actions/open-position/open-position.action.d.ts +1 -1
  28. package/dist/actions/open-position/open-position.action.d.ts.map +1 -1
  29. package/dist/actions/open-position/open-position.action.js +282 -224
  30. package/dist/actions/open-position/open-position.action.js.map +1 -1
  31. package/dist/actions/position-tracker/position-tracker.action.d.ts.map +1 -1
  32. package/dist/actions/position-tracker/position-tracker.action.js +3 -6
  33. package/dist/actions/position-tracker/position-tracker.action.js.map +1 -1
  34. package/dist/cli/guide-commands.d.ts.map +1 -1
  35. package/dist/cli/guide-commands.js +61 -0
  36. package/dist/cli/guide-commands.js.map +1 -1
  37. package/dist/cli/senpi-commands.d.ts +14 -0
  38. package/dist/cli/senpi-commands.d.ts.map +1 -1
  39. package/dist/cli/senpi-commands.js +390 -2
  40. package/dist/cli/senpi-commands.js.map +1 -1
  41. package/dist/dsl/engine-client/event-mapping.d.ts.map +1 -1
  42. package/dist/dsl/engine-client/event-mapping.js +0 -3
  43. package/dist/dsl/engine-client/event-mapping.js.map +1 -1
  44. package/dist/dsl/events/build-closed-event.d.ts.map +1 -1
  45. package/dist/dsl/events/build-closed-event.js +0 -1
  46. package/dist/dsl/events/build-closed-event.js.map +1 -1
  47. package/dist/dsl/events/handlers.d.ts.map +1 -1
  48. package/dist/dsl/events/handlers.js +2 -4
  49. package/dist/dsl/events/handlers.js.map +1 -1
  50. package/dist/dsl/events/initial-state.d.ts.map +1 -1
  51. package/dist/dsl/events/initial-state.js +1 -0
  52. package/dist/dsl/events/initial-state.js.map +1 -1
  53. package/dist/dsl/monitor/create-monitor.d.ts +3 -0
  54. package/dist/dsl/monitor/create-monitor.d.ts.map +1 -1
  55. package/dist/dsl/monitor/create-monitor.js +76 -58
  56. package/dist/dsl/monitor/create-monitor.js.map +1 -1
  57. package/dist/dsl/monitor/dsl-failure-events.d.ts +42 -0
  58. package/dist/dsl/monitor/dsl-failure-events.d.ts.map +1 -0
  59. package/dist/dsl/monitor/dsl-failure-events.js +73 -0
  60. package/dist/dsl/monitor/dsl-failure-events.js.map +1 -0
  61. package/dist/dsl/monitor/process-one-position.d.ts +2 -1
  62. package/dist/dsl/monitor/process-one-position.d.ts.map +1 -1
  63. package/dist/dsl/monitor/process-one-position.js +130 -196
  64. package/dist/dsl/monitor/process-one-position.js.map +1 -1
  65. package/dist/dsl/plugin/index.d.ts +10 -0
  66. package/dist/dsl/plugin/index.d.ts.map +1 -1
  67. package/dist/dsl/plugin/index.js +48 -4
  68. package/dist/dsl/plugin/index.js.map +1 -1
  69. package/dist/dsl/plugin/options.d.ts +3 -0
  70. package/dist/dsl/plugin/options.d.ts.map +1 -1
  71. package/dist/health/types.d.ts +14 -0
  72. package/dist/health/types.d.ts.map +1 -1
  73. package/dist/health/types.js.map +1 -1
  74. package/dist/index.d.ts +1 -0
  75. package/dist/index.d.ts.map +1 -1
  76. package/dist/index.js +264 -79
  77. package/dist/index.js.map +1 -1
  78. package/dist/risk/risk-audit-log.d.ts +7 -0
  79. package/dist/risk/risk-audit-log.d.ts.map +1 -1
  80. package/dist/risk/risk-audit-log.js +48 -1
  81. package/dist/risk/risk-audit-log.js.map +1 -1
  82. package/dist/runtime/__tests__/helpers/runtime-gateway-harness.d.ts +2 -0
  83. package/dist/runtime/__tests__/helpers/runtime-gateway-harness.d.ts.map +1 -1
  84. package/dist/runtime/__tests__/helpers/runtime-gateway-harness.js +24 -3
  85. package/dist/runtime/__tests__/helpers/runtime-gateway-harness.js.map +1 -1
  86. package/dist/runtime/auto-update/coordinator.js +2 -2
  87. package/dist/runtime/auto-update/coordinator.js.map +1 -1
  88. package/dist/runtime/create-actions.d.ts.map +1 -1
  89. package/dist/runtime/create-actions.js +40 -15
  90. package/dist/runtime/create-actions.js.map +1 -1
  91. package/dist/runtime/create-runtime-context.d.ts +1 -1
  92. package/dist/runtime/create-runtime-context.d.ts.map +1 -1
  93. package/dist/runtime/create-scanner-module.d.ts +2 -1
  94. package/dist/runtime/create-scanner-module.d.ts.map +1 -1
  95. package/dist/runtime/create-scanner-module.js +2 -1
  96. package/dist/runtime/create-scanner-module.js.map +1 -1
  97. package/dist/runtime/domain-events.d.ts +43 -0
  98. package/dist/runtime/domain-events.d.ts.map +1 -0
  99. package/dist/runtime/domain-events.js +181 -0
  100. package/dist/runtime/domain-events.js.map +1 -0
  101. package/dist/runtime/lifecycle-events.d.ts +86 -0
  102. package/dist/runtime/lifecycle-events.d.ts.map +1 -0
  103. package/dist/runtime/lifecycle-events.js +200 -0
  104. package/dist/runtime/lifecycle-events.js.map +1 -0
  105. package/dist/runtime/notifications.js +2 -2
  106. package/dist/runtime/notifications.js.map +1 -1
  107. package/dist/{tracking → runtime}/position-id-registry.d.ts +14 -1
  108. package/dist/runtime/position-id-registry.d.ts.map +1 -0
  109. package/dist/{tracking → runtime}/position-id-registry.js +20 -3
  110. package/dist/runtime/position-id-registry.js.map +1 -0
  111. package/dist/runtime/run.d.ts +2 -4
  112. package/dist/runtime/run.d.ts.map +1 -1
  113. package/dist/runtime/run.js.map +1 -1
  114. package/dist/runtime/runtime-schema.d.ts +276 -588
  115. package/dist/runtime/runtime-schema.d.ts.map +1 -1
  116. package/dist/runtime/runtime-schema.js +8 -28
  117. package/dist/runtime/runtime-schema.js.map +1 -1
  118. package/dist/runtime/runtime.d.ts +23 -9
  119. package/dist/runtime/runtime.d.ts.map +1 -1
  120. package/dist/runtime/runtime.js +276 -248
  121. package/dist/runtime/runtime.js.map +1 -1
  122. package/dist/runtime/strategy-lifecycle.d.ts.map +1 -1
  123. package/dist/runtime/strategy-lifecycle.js +13 -1
  124. package/dist/runtime/strategy-lifecycle.js.map +1 -1
  125. package/dist/runtime/supervisor/long-running-supervisor.d.ts +3 -0
  126. package/dist/runtime/supervisor/long-running-supervisor.d.ts.map +1 -1
  127. package/dist/runtime/supervisor/long-running-supervisor.js +27 -53
  128. package/dist/runtime/supervisor/long-running-supervisor.js.map +1 -1
  129. package/dist/runtime-api/config.d.ts +2 -2
  130. package/dist/runtime-api/config.js +4 -4
  131. package/dist/runtime-api/config.js.map +1 -1
  132. package/dist/runtime-api/handlers/ingest-signals.d.ts +5 -3
  133. package/dist/runtime-api/handlers/ingest-signals.d.ts.map +1 -1
  134. package/dist/runtime-api/handlers/ingest-signals.js +14 -5
  135. package/dist/runtime-api/handlers/ingest-signals.js.map +1 -1
  136. package/dist/runtime-api/intake/ingest-mutex.d.ts +16 -0
  137. package/dist/runtime-api/intake/ingest-mutex.d.ts.map +1 -0
  138. package/dist/runtime-api/intake/ingest-mutex.js +18 -0
  139. package/dist/runtime-api/intake/ingest-mutex.js.map +1 -0
  140. package/dist/runtime-api/intake/intake-events.d.ts +44 -0
  141. package/dist/runtime-api/intake/intake-events.d.ts.map +1 -0
  142. package/dist/runtime-api/intake/intake-events.js +131 -0
  143. package/dist/runtime-api/intake/intake-events.js.map +1 -0
  144. package/dist/runtime-api/intake/intake-mount.d.ts.map +1 -1
  145. package/dist/runtime-api/intake/intake-mount.js +8 -2
  146. package/dist/runtime-api/intake/intake-mount.js.map +1 -1
  147. package/dist/runtime-api/intake/scanner-launcher.d.ts +2 -0
  148. package/dist/runtime-api/intake/scanner-launcher.d.ts.map +1 -1
  149. package/dist/runtime-api/intake/scanner-launcher.js +58 -15
  150. package/dist/runtime-api/intake/scanner-launcher.js.map +1 -1
  151. package/dist/runtime-api/intake/scanner-registry.d.ts +3 -0
  152. package/dist/runtime-api/intake/scanner-registry.d.ts.map +1 -1
  153. package/dist/runtime-api/intake/scanner-registry.js +3 -0
  154. package/dist/runtime-api/intake/scanner-registry.js.map +1 -1
  155. package/dist/runtime-api/intake/supervisor-events.d.ts +61 -0
  156. package/dist/runtime-api/intake/supervisor-events.d.ts.map +1 -0
  157. package/dist/runtime-api/intake/supervisor-events.js +173 -0
  158. package/dist/runtime-api/intake/supervisor-events.js.map +1 -0
  159. package/dist/runtime-api/routes/signals.d.ts +1 -1
  160. package/dist/runtime-api/routes/signals.d.ts.map +1 -1
  161. package/dist/runtime-api/routes/signals.js +121 -35
  162. package/dist/runtime-api/routes/signals.js.map +1 -1
  163. package/dist/runtime-api/server.d.ts.map +1 -1
  164. package/dist/runtime-api/server.js +10 -1
  165. package/dist/runtime-api/server.js.map +1 -1
  166. package/dist/scanners/engine/data-providers.d.ts +3 -0
  167. package/dist/scanners/engine/data-providers.d.ts.map +1 -1
  168. package/dist/scanners/engine/data-providers.js.map +1 -1
  169. package/dist/scanners/engine/engine.d.ts +18 -0
  170. package/dist/scanners/engine/engine.d.ts.map +1 -1
  171. package/dist/scanners/engine/engine.js +96 -2
  172. package/dist/scanners/engine/engine.js.map +1 -1
  173. package/dist/scanners/engine/input-resolver.d.ts.map +1 -1
  174. package/dist/scanners/engine/input-resolver.js +9 -7
  175. package/dist/scanners/engine/input-resolver.js.map +1 -1
  176. package/dist/scanners/runtime-module.d.ts +3 -0
  177. package/dist/scanners/runtime-module.d.ts.map +1 -1
  178. package/dist/scanners/runtime-module.js +7 -0
  179. package/dist/scanners/runtime-module.js.map +1 -1
  180. package/dist/senpi/client.d.ts +10 -0
  181. package/dist/senpi/client.d.ts.map +1 -1
  182. package/dist/senpi/client.js +113 -46
  183. package/dist/senpi/client.js.map +1 -1
  184. package/dist/skills-manager/bootstrap.d.ts.map +1 -1
  185. package/dist/skills-manager/bootstrap.js +22 -33
  186. package/dist/skills-manager/bootstrap.js.map +1 -1
  187. package/dist/skills-manager/clone-groups.d.ts +20 -0
  188. package/dist/skills-manager/clone-groups.d.ts.map +1 -0
  189. package/dist/skills-manager/clone-groups.js +45 -0
  190. package/dist/skills-manager/clone-groups.js.map +1 -0
  191. package/dist/skills-manager/coordinator.d.ts.map +1 -1
  192. package/dist/skills-manager/coordinator.js +111 -75
  193. package/dist/skills-manager/coordinator.js.map +1 -1
  194. package/dist/skills-manager/manifest.d.ts +24 -0
  195. package/dist/skills-manager/manifest.d.ts.map +1 -1
  196. package/dist/skills-manager/manifest.js +23 -10
  197. package/dist/skills-manager/manifest.js.map +1 -1
  198. package/dist/skills-manager/skills-manifest.json +12 -7
  199. package/dist/skills-manager/types.d.ts +12 -0
  200. package/dist/skills-manager/types.d.ts.map +1 -1
  201. package/dist/state/state-events.d.ts +13 -0
  202. package/dist/state/state-events.d.ts.map +1 -0
  203. package/dist/state/state-events.js +22 -0
  204. package/dist/state/state-events.js.map +1 -0
  205. package/dist/state/state-manager.d.ts.map +1 -1
  206. package/dist/state/state-manager.js +14 -1
  207. package/dist/state/state-manager.js.map +1 -1
  208. package/dist/telemetry/attributes.d.ts +13 -0
  209. package/dist/telemetry/attributes.d.ts.map +1 -0
  210. package/dist/telemetry/attributes.js +22 -0
  211. package/dist/telemetry/attributes.js.map +1 -0
  212. package/dist/{tracking → telemetry}/context.d.ts +12 -5
  213. package/dist/telemetry/context.d.ts.map +1 -0
  214. package/dist/{tracking → telemetry}/context.js +4 -4
  215. package/dist/telemetry/context.js.map +1 -0
  216. package/dist/{recording/records.d.ts → telemetry/event-builders.d.ts} +145 -33
  217. package/dist/telemetry/event-builders.d.ts.map +1 -0
  218. package/dist/{recording/wiring/record-builders.js → telemetry/event-builders.js} +94 -40
  219. package/dist/telemetry/event-builders.js.map +1 -0
  220. package/dist/telemetry/event-store.d.ts +66 -0
  221. package/dist/telemetry/event-store.d.ts.map +1 -0
  222. package/dist/telemetry/event-store.js +202 -0
  223. package/dist/telemetry/event-store.js.map +1 -0
  224. package/dist/telemetry/identity.d.ts +72 -0
  225. package/dist/telemetry/identity.d.ts.map +1 -0
  226. package/dist/{recording/wiring → telemetry}/identity.js +6 -2
  227. package/dist/telemetry/identity.js.map +1 -0
  228. package/dist/telemetry/metrics.d.ts +169 -0
  229. package/dist/telemetry/metrics.d.ts.map +1 -0
  230. package/dist/telemetry/metrics.js +437 -0
  231. package/dist/telemetry/metrics.js.map +1 -0
  232. package/dist/telemetry/otel-sdk.d.ts +93 -0
  233. package/dist/telemetry/otel-sdk.d.ts.map +1 -0
  234. package/dist/telemetry/otel-sdk.js +297 -0
  235. package/dist/telemetry/otel-sdk.js.map +1 -0
  236. package/dist/telemetry/spans/constants.d.ts +12 -0
  237. package/dist/telemetry/spans/constants.d.ts.map +1 -0
  238. package/dist/telemetry/spans/constants.js +12 -0
  239. package/dist/telemetry/spans/constants.js.map +1 -0
  240. package/dist/telemetry/spans/gen-ai.d.ts +74 -0
  241. package/dist/telemetry/spans/gen-ai.d.ts.map +1 -0
  242. package/dist/telemetry/spans/gen-ai.js +339 -0
  243. package/dist/telemetry/spans/gen-ai.js.map +1 -0
  244. package/dist/telemetry/spans/index.d.ts +11 -0
  245. package/dist/telemetry/spans/index.d.ts.map +1 -0
  246. package/dist/telemetry/spans/index.js +11 -0
  247. package/dist/telemetry/spans/index.js.map +1 -0
  248. package/dist/{tracking → telemetry}/spans/redact-pii.d.ts +19 -21
  249. package/dist/telemetry/spans/redact-pii.d.ts.map +1 -0
  250. package/dist/{tracking → telemetry}/spans/redact-pii.js +35 -32
  251. package/dist/telemetry/spans/redact-pii.js.map +1 -0
  252. package/dist/telemetry/spans/sanitize-payload.d.ts.map +1 -0
  253. package/dist/telemetry/spans/sanitize-payload.js.map +1 -0
  254. package/dist/telemetry/spans/span-hooks.d.ts +18 -0
  255. package/dist/telemetry/spans/span-hooks.d.ts.map +1 -0
  256. package/dist/telemetry/spans/span-hooks.js +764 -0
  257. package/dist/telemetry/spans/span-hooks.js.map +1 -0
  258. package/dist/telemetry/tool-plane.d.ts +31 -0
  259. package/dist/telemetry/tool-plane.d.ts.map +1 -0
  260. package/dist/telemetry/tool-plane.js +70 -0
  261. package/dist/telemetry/tool-plane.js.map +1 -0
  262. package/dist/telemetry/trace-identity.d.ts +32 -0
  263. package/dist/telemetry/trace-identity.d.ts.map +1 -0
  264. package/dist/telemetry/trace-identity.js +62 -0
  265. package/dist/telemetry/trace-identity.js.map +1 -0
  266. package/dist/telemetry/tracing.d.ts +33 -0
  267. package/dist/telemetry/tracing.d.ts.map +1 -0
  268. package/dist/telemetry/tracing.js +70 -0
  269. package/dist/telemetry/tracing.js.map +1 -0
  270. package/dist/types/dsl/index.d.ts +8 -9
  271. package/dist/types/dsl/index.d.ts.map +1 -1
  272. package/dist/types/runtime.d.ts +1 -1
  273. package/dist/types/runtime.d.ts.map +1 -1
  274. package/dist/types/scanner.d.ts +2 -0
  275. package/dist/types/scanner.d.ts.map +1 -1
  276. package/dist/utils/event-catalog.d.ts +506 -0
  277. package/dist/utils/event-catalog.d.ts.map +1 -0
  278. package/dist/utils/event-catalog.js +142 -0
  279. package/dist/utils/event-catalog.js.map +1 -0
  280. package/dist/utils/logger.d.ts +63 -5
  281. package/dist/utils/logger.d.ts.map +1 -1
  282. package/dist/utils/logger.js +360 -27
  283. package/dist/utils/logger.js.map +1 -1
  284. package/dist/utils/wallet-address.d.ts +3 -0
  285. package/dist/utils/wallet-address.d.ts.map +1 -0
  286. package/dist/utils/wallet-address.js +17 -0
  287. package/dist/utils/wallet-address.js.map +1 -0
  288. package/openclaw.plugin.json +20 -6
  289. package/package.json +10 -2
  290. package/dist/actions/tracking-helpers.d.ts +0 -28
  291. package/dist/actions/tracking-helpers.d.ts.map +0 -1
  292. package/dist/actions/tracking-helpers.js +0 -93
  293. package/dist/actions/tracking-helpers.js.map +0 -1
  294. package/dist/recording/emitter.d.ts +0 -27
  295. package/dist/recording/emitter.d.ts.map +0 -1
  296. package/dist/recording/emitter.js +0 -2
  297. package/dist/recording/emitter.js.map +0 -1
  298. package/dist/recording/identity.d.ts +0 -34
  299. package/dist/recording/identity.d.ts.map +0 -1
  300. package/dist/recording/identity.js +0 -2
  301. package/dist/recording/identity.js.map +0 -1
  302. package/dist/recording/index.d.ts +0 -11
  303. package/dist/recording/index.d.ts.map +0 -1
  304. package/dist/recording/index.js +0 -2
  305. package/dist/recording/index.js.map +0 -1
  306. package/dist/recording/noop-emitter.d.ts +0 -23
  307. package/dist/recording/noop-emitter.d.ts.map +0 -1
  308. package/dist/recording/noop-emitter.js +0 -22
  309. package/dist/recording/noop-emitter.js.map +0 -1
  310. package/dist/recording/otel/attributes.d.ts +0 -35
  311. package/dist/recording/otel/attributes.d.ts.map +0 -1
  312. package/dist/recording/otel/attributes.js +0 -131
  313. package/dist/recording/otel/attributes.js.map +0 -1
  314. package/dist/recording/otel/constants.d.ts +0 -123
  315. package/dist/recording/otel/constants.d.ts.map +0 -1
  316. package/dist/recording/otel/constants.js +0 -172
  317. package/dist/recording/otel/constants.js.map +0 -1
  318. package/dist/recording/otel/ids.d.ts +0 -25
  319. package/dist/recording/otel/ids.d.ts.map +0 -1
  320. package/dist/recording/otel/ids.js +0 -37
  321. package/dist/recording/otel/ids.js.map +0 -1
  322. package/dist/recording/otel/index.d.ts +0 -13
  323. package/dist/recording/otel/index.d.ts.map +0 -1
  324. package/dist/recording/otel/index.js +0 -9
  325. package/dist/recording/otel/index.js.map +0 -1
  326. package/dist/recording/otel/mappers.d.ts +0 -100
  327. package/dist/recording/otel/mappers.d.ts.map +0 -1
  328. package/dist/recording/otel/mappers.js +0 -683
  329. package/dist/recording/otel/mappers.js.map +0 -1
  330. package/dist/recording/otel/otel-emitter.d.ts +0 -43
  331. package/dist/recording/otel/otel-emitter.d.ts.map +0 -1
  332. package/dist/recording/otel/otel-emitter.js +0 -99
  333. package/dist/recording/otel/otel-emitter.js.map +0 -1
  334. package/dist/recording/otel/redaction.d.ts +0 -47
  335. package/dist/recording/otel/redaction.d.ts.map +0 -1
  336. package/dist/recording/otel/redaction.js +0 -88
  337. package/dist/recording/otel/redaction.js.map +0 -1
  338. package/dist/recording/records.d.ts.map +0 -1
  339. package/dist/recording/records.js +0 -14
  340. package/dist/recording/records.js.map +0 -1
  341. package/dist/recording/transport/batcher.d.ts +0 -59
  342. package/dist/recording/transport/batcher.d.ts.map +0 -1
  343. package/dist/recording/transport/batcher.js +0 -234
  344. package/dist/recording/transport/batcher.js.map +0 -1
  345. package/dist/recording/transport/client.d.ts +0 -41
  346. package/dist/recording/transport/client.d.ts.map +0 -1
  347. package/dist/recording/transport/client.js +0 -69
  348. package/dist/recording/transport/client.js.map +0 -1
  349. package/dist/recording/transport/config.d.ts +0 -53
  350. package/dist/recording/transport/config.d.ts.map +0 -1
  351. package/dist/recording/transport/config.js +0 -41
  352. package/dist/recording/transport/config.js.map +0 -1
  353. package/dist/recording/transport/index.d.ts +0 -16
  354. package/dist/recording/transport/index.d.ts.map +0 -1
  355. package/dist/recording/transport/index.js +0 -12
  356. package/dist/recording/transport/index.js.map +0 -1
  357. package/dist/recording/transport/rows.d.ts +0 -88
  358. package/dist/recording/transport/rows.d.ts.map +0 -1
  359. package/dist/recording/transport/rows.js +0 -15
  360. package/dist/recording/transport/rows.js.map +0 -1
  361. package/dist/recording/wiring/emitter-factory.d.ts +0 -39
  362. package/dist/recording/wiring/emitter-factory.d.ts.map +0 -1
  363. package/dist/recording/wiring/emitter-factory.js +0 -62
  364. package/dist/recording/wiring/emitter-factory.js.map +0 -1
  365. package/dist/recording/wiring/identity.d.ts +0 -27
  366. package/dist/recording/wiring/identity.d.ts.map +0 -1
  367. package/dist/recording/wiring/identity.js.map +0 -1
  368. package/dist/recording/wiring/index.d.ts +0 -12
  369. package/dist/recording/wiring/index.d.ts.map +0 -1
  370. package/dist/recording/wiring/index.js +0 -9
  371. package/dist/recording/wiring/index.js.map +0 -1
  372. package/dist/recording/wiring/record-builders.d.ts +0 -107
  373. package/dist/recording/wiring/record-builders.d.ts.map +0 -1
  374. package/dist/recording/wiring/record-builders.js.map +0 -1
  375. package/dist/recording/wiring/subscriber.d.ts +0 -28
  376. package/dist/recording/wiring/subscriber.d.ts.map +0 -1
  377. package/dist/recording/wiring/subscriber.js +0 -173
  378. package/dist/recording/wiring/subscriber.js.map +0 -1
  379. package/dist/recording/wiring/values.d.ts +0 -19
  380. package/dist/recording/wiring/values.d.ts.map +0 -1
  381. package/dist/recording/wiring/values.js +0 -49
  382. package/dist/recording/wiring/values.js.map +0 -1
  383. package/dist/tracking/build-rehydrate-items.d.ts +0 -15
  384. package/dist/tracking/build-rehydrate-items.d.ts.map +0 -1
  385. package/dist/tracking/build-rehydrate-items.js +0 -19
  386. package/dist/tracking/build-rehydrate-items.js.map +0 -1
  387. package/dist/tracking/constants.d.ts +0 -24
  388. package/dist/tracking/constants.d.ts.map +0 -1
  389. package/dist/tracking/constants.js +0 -52
  390. package/dist/tracking/constants.js.map +0 -1
  391. package/dist/tracking/context.d.ts.map +0 -1
  392. package/dist/tracking/context.js.map +0 -1
  393. package/dist/tracking/index.d.ts +0 -16
  394. package/dist/tracking/index.d.ts.map +0 -1
  395. package/dist/tracking/index.js +0 -11
  396. package/dist/tracking/index.js.map +0 -1
  397. package/dist/tracking/plugin-event-tracker.d.ts +0 -13
  398. package/dist/tracking/plugin-event-tracker.d.ts.map +0 -1
  399. package/dist/tracking/plugin-event-tracker.js +0 -27
  400. package/dist/tracking/plugin-event-tracker.js.map +0 -1
  401. package/dist/tracking/position-id-registry.d.ts.map +0 -1
  402. package/dist/tracking/position-id-registry.js.map +0 -1
  403. package/dist/tracking/spans/constants.d.ts +0 -19
  404. package/dist/tracking/spans/constants.d.ts.map +0 -1
  405. package/dist/tracking/spans/constants.js +0 -31
  406. package/dist/tracking/spans/constants.js.map +0 -1
  407. package/dist/tracking/spans/fan-out-span-transport.d.ts +0 -22
  408. package/dist/tracking/spans/fan-out-span-transport.d.ts.map +0 -1
  409. package/dist/tracking/spans/fan-out-span-transport.js +0 -49
  410. package/dist/tracking/spans/fan-out-span-transport.js.map +0 -1
  411. package/dist/tracking/spans/index.d.ts +0 -13
  412. package/dist/tracking/spans/index.d.ts.map +0 -1
  413. package/dist/tracking/spans/index.js +0 -16
  414. package/dist/tracking/spans/index.js.map +0 -1
  415. package/dist/tracking/spans/otel/fit-row-budget.d.ts +0 -22
  416. package/dist/tracking/spans/otel/fit-row-budget.d.ts.map +0 -1
  417. package/dist/tracking/spans/otel/fit-row-budget.js +0 -91
  418. package/dist/tracking/spans/otel/fit-row-budget.js.map +0 -1
  419. package/dist/tracking/spans/otel/map-span-to-trace-row.d.ts +0 -16
  420. package/dist/tracking/spans/otel/map-span-to-trace-row.d.ts.map +0 -1
  421. package/dist/tracking/spans/otel/map-span-to-trace-row.js +0 -227
  422. package/dist/tracking/spans/otel/map-span-to-trace-row.js.map +0 -1
  423. package/dist/tracking/spans/otel/recording-span-transport.d.ts +0 -43
  424. package/dist/tracking/spans/otel/recording-span-transport.d.ts.map +0 -1
  425. package/dist/tracking/spans/otel/recording-span-transport.js +0 -67
  426. package/dist/tracking/spans/otel/recording-span-transport.js.map +0 -1
  427. package/dist/tracking/spans/otel/span-ids.d.ts +0 -22
  428. package/dist/tracking/spans/otel/span-ids.d.ts.map +0 -1
  429. package/dist/tracking/spans/otel/span-ids.js +0 -32
  430. package/dist/tracking/spans/otel/span-ids.js.map +0 -1
  431. package/dist/tracking/spans/plugin-span-tracker.d.ts +0 -9
  432. package/dist/tracking/spans/plugin-span-tracker.d.ts.map +0 -1
  433. package/dist/tracking/spans/plugin-span-tracker.js +0 -115
  434. package/dist/tracking/spans/plugin-span-tracker.js.map +0 -1
  435. package/dist/tracking/spans/redact-pii.d.ts.map +0 -1
  436. package/dist/tracking/spans/redact-pii.js.map +0 -1
  437. package/dist/tracking/spans/sanitize-payload.d.ts.map +0 -1
  438. package/dist/tracking/spans/sanitize-payload.js.map +0 -1
  439. package/dist/tracking/spans/span-hooks.d.ts +0 -28
  440. package/dist/tracking/spans/span-hooks.d.ts.map +0 -1
  441. package/dist/tracking/spans/span-hooks.js +0 -409
  442. package/dist/tracking/spans/span-hooks.js.map +0 -1
  443. package/dist/tracking/spans/span-tracker.d.ts +0 -133
  444. package/dist/tracking/spans/span-tracker.d.ts.map +0 -1
  445. package/dist/tracking/spans/span-tracker.js +0 -721
  446. package/dist/tracking/spans/span-tracker.js.map +0 -1
  447. package/dist/tracking/spans/span-transport.d.ts +0 -71
  448. package/dist/tracking/spans/span-transport.d.ts.map +0 -1
  449. package/dist/tracking/spans/span-transport.js +0 -240
  450. package/dist/tracking/spans/span-transport.js.map +0 -1
  451. package/dist/tracking/spans/types.d.ts +0 -101
  452. package/dist/tracking/spans/types.d.ts.map +0 -1
  453. package/dist/tracking/spans/types.js +0 -6
  454. package/dist/tracking/spans/types.js.map +0 -1
  455. package/dist/tracking/tracker.d.ts +0 -30
  456. package/dist/tracking/tracker.d.ts.map +0 -1
  457. package/dist/tracking/tracker.js +0 -66
  458. package/dist/tracking/tracker.js.map +0 -1
  459. package/dist/tracking/tracking-handler.d.ts +0 -12
  460. package/dist/tracking/tracking-handler.d.ts.map +0 -1
  461. package/dist/tracking/tracking-handler.js +0 -148
  462. package/dist/tracking/tracking-handler.js.map +0 -1
  463. package/dist/tracking/transport.d.ts +0 -35
  464. package/dist/tracking/transport.d.ts.map +0 -1
  465. package/dist/tracking/transport.js +0 -133
  466. package/dist/tracking/transport.js.map +0 -1
  467. package/dist/tracking/types.d.ts +0 -21
  468. package/dist/tracking/types.d.ts.map +0 -1
  469. package/dist/tracking/types.js +0 -6
  470. package/dist/tracking/types.js.map +0 -1
  471. /package/dist/{tracking → telemetry}/spans/sanitize-payload.d.ts +0 -0
  472. /package/dist/{tracking → telemetry}/spans/sanitize-payload.js +0 -0
package/dist/index.js CHANGED
@@ -11,21 +11,10 @@
11
11
  * that reason. Keeping every export in a single file (this one) avoids
12
12
  * the loader's relative-import path entirely.
13
13
  */
14
- // dd-trace init MUST be the first executable statement in this file so it
15
- // patches Node core modules (http, fs, etc.) before any traceable resource is
16
- // constructed by the imports below. Gated on DD_TRACE_ENABLED=true so unit
17
- // tests and standalone CLI invocations do not pay the init cost.
18
- // `createRequire` is used because `dd-trace` is a CJS module and our
19
- // tsconfig uses Node16 modules — a top-level `import "dd-trace"` would
20
- // be hoisted above this gate by the bundler/loader.
21
- import { createRequire } from "node:module";
22
- const __require = createRequire(import.meta.url);
23
- if (process.env.DD_TRACE_ENABLED === "true") {
24
- __require("dd-trace").init();
25
- }
26
14
  import { readFileSync } from "node:fs";
27
15
  import { join, dirname } from "node:path";
28
16
  import { SenpiClient } from "./senpi/client.js";
17
+ import { AuditQueryError } from "./runtime/audit-query.types.js";
29
18
  import { buildRuntimeStateDir, archiveStateDir } from "./runtime/state-layout.js";
30
19
  import { registerSenpiCli } from "./cli/senpi-commands.js";
31
20
  import { readSenpiCliStore, resolveSenpiApiKeyFromStore, resolveSenpiBaseStateDir, resolveTelegramChatIdFromStore, } from "./cli/senpi-cli-config.js";
@@ -39,21 +28,28 @@ import { createScannerProvidersForRun } from "./runtime/create-scanner-providers
39
28
  import { initDsl } from "./dsl/index.js";
40
29
  import { initHealth } from "./health/index.js";
41
30
  import { initRisk } from "./risk/index.js";
31
+ import { readRiskAuditEntries } from "./risk/risk-audit-log.js";
32
+ import { readEvents } from "./telemetry/event-store.js";
42
33
  import { VERSION } from "./version.js";
43
34
  import { resolvePackageName } from "./runtime/auto-update/resolve-package-name.js";
44
35
  import { runOpenClawPluginsUpdate } from "./runtime/auto-update/run-update-command.js";
45
- import { BUS_EVENT_MAP } from "./tracking/constants.js";
46
- import { createPluginEventTracker } from "./tracking/plugin-event-tracker.js";
47
- import { createPluginSpanTracker, registerSpanHooks, setDefaultSpanTracker, } from "./tracking/spans/index.js";
36
+ import { registerSpanHooks } from "./telemetry/spans/index.js";
37
+ import { initDefaultPiiRedactor } from "./telemetry/spans/redact-pii.js";
38
+ import { initOtelSdk, shutdownOtelSdk } from "./telemetry/otel-sdk.js";
48
39
  import { getLogLevel, getLogLevelSource, parseLogLevel, setErrorNotifier, setLogLevel, } from "./utils/logger.js";
49
40
  import { ExternalScannerIngestError, } from "./scanners/external-scanner-receiver.js";
50
41
  import { createLogger } from "./utils/logger.js";
42
+ import { EVENT_NAME, eventAttrs } from "./utils/event-catalog.js";
43
+ import { emitEvent } from "./actions/event-derivation.js";
44
+ import { buildRuntimeCreatedEvent, buildRuntimeDeletedEvent } from "./runtime/lifecycle-events.js";
45
+ import { isWalletAddress } from "./utils/wallet-address.js";
51
46
  import { fileURLToPath } from "node:url";
52
47
  import { loadApiConfig } from "./runtime-api/config.js";
53
48
  import { startApi } from "./runtime-api/lifecycle.js";
54
49
  import { ingestSignalsHandler } from "./runtime-api/handlers/ingest-signals.js";
55
50
  import { createIntakeContext } from "./runtime-api/intake/intake-context.js";
56
51
  import { wireRuntime, intakeUrlFor } from "./runtime-api/intake/intake-mount.js";
52
+ import { ingestDispatchMutex, ingestDispatchKey } from "./runtime-api/intake/ingest-mutex.js";
57
53
  import { loadRuntimeConfig } from "./runtime/load-runtime-config.js";
58
54
  /** Initialize all core features (DSL, risk, health) on the given event bus. */
59
55
  export function initCore(bus) {
@@ -140,8 +136,11 @@ function formatSharedLoggerErrorNotification(payload) {
140
136
  `level: ${payload.level}`,
141
137
  `message: ${payload.message}`,
142
138
  ];
143
- if (payload.meta !== undefined) {
144
- lines.push(`meta:\n${stringifyForTelegram(payload.meta)}`);
139
+ if (payload.exception !== undefined) {
140
+ lines.push(`exception:\n${stringifyForTelegram(payload.exception)}`);
141
+ }
142
+ if (payload.attributes !== undefined) {
143
+ lines.push(`attributes:\n${stringifyForTelegram(payload.attributes)}`);
145
144
  }
146
145
  return trimTelegramMessage(lines.join("\n"));
147
146
  }
@@ -267,16 +266,27 @@ const senpiRuntimePlugin = {
267
266
  // mcpTransport = gateway-injected (no eager connect); apiKey = self-managed SenpiClient
268
267
  // (lazy connect — the R7 boot-resilience path). No secret is logged, only presence + url.
269
268
  pluginLogger.info(`[senpi-runtime] MCP transport: ${mcpTransport ? "mcpTransport (gateway-injected)" : "apiKey (self-managed SenpiClient)"}; mcpUrl=${process.env.SENPI_MCP_URL ?? "(default)"}`);
270
- const pluginEventTracker = createPluginEventTracker(apiKey ?? process.env.SENPI_AUTH_TOKEN ?? process.env.SENPI_API_KEY);
271
- // Span telemetry — one tracker per gateway, shared across all hosted runtimes
272
- // and OpenClaw hook activity. Captures llm/tool/subagent/agent_end via
273
- // OpenClaw plugin hooks; direct-SDK paths (AnthropicLlmDecision) emit
274
- // through the same tracker via factory injection.
275
- const pluginSpanTracker = createPluginSpanTracker(apiKey ?? process.env.SENPI_AUTH_TOKEN ?? process.env.SENPI_API_KEY);
276
- setDefaultSpanTracker(pluginSpanTracker);
269
+ // Register the process-wide default PII redactor at boot (always on, no env gate)
270
+ // so `logger.event()` redact fields are scrubbed on the live path. Fire-and-forget;
271
+ // see initDefaultPiiRedactor in telemetry/spans/redact-pii.ts.
272
+ initDefaultPiiRedactor();
273
+ // OTel SDK stand-up at process scope. register() must stay synchronous (the gateway
274
+ // loader doesn't await it; awaiting init would defer the registrations below), so it's
275
+ // fire-and-forget — the hooks resolve their tracer lazily at fire time, by which point
276
+ // init has run. Self-guarding; see src/telemetry/otel-sdk.ts.
277
+ void initOtelSdk({
278
+ userToken: apiKey ?? process.env.SENPI_AUTH_TOKEN ?? process.env.SENPI_API_KEY,
279
+ serviceVersion: VERSION,
280
+ }).catch((err) => {
281
+ pluginLogger.warn("[senpi-runtime] OTel SDK init failed", {
282
+ err: err instanceof Error ? err.message : String(err),
283
+ });
284
+ });
285
+ // Agent telemetry — gateway hooks emit gen_ai spans (llm/tool/subagent) through
286
+ // the shared tracer; on-site MCP calls emit their own spans from SenpiClient.
277
287
  try {
278
- registerSpanHooks({ api, tracker: pluginSpanTracker });
279
- pluginLogger.info("[senpi-runtime] span hooks registered (9 hooks)");
288
+ registerSpanHooks({ api });
289
+ pluginLogger.info("[senpi-runtime] gen_ai span hooks registered (9 hooks)");
280
290
  }
281
291
  catch (err) {
282
292
  pluginLogger.warn("[senpi-runtime] failed to register span hooks", {
@@ -323,6 +333,24 @@ const senpiRuntimePlugin = {
323
333
  // PluginLogger surface (info/warn/error) lacks `debug`, while the
324
334
  // Logger contract used by `runtime-api/` includes it.
325
335
  const apiLogger = createLogger("[senpi-core][api]");
336
+ // A gateway seam failed to wire/launch a runtime's external scanner stack: the runtime is up but
337
+ // runs blind on internal scanners only. Two records, by design: a first-class `runtime.scanners_unwired`
338
+ // event (the queryable/alertable fact, by phase) and the migrated exception-form `logger.error`
339
+ // (carries the stack + trace context, and fans the error notifier so a blind runtime still pages).
340
+ const eventScannersUnwired = (phase, runtimeId, wallet, message, error) => {
341
+ apiLogger.event(EVENT_NAME.runtimeScannersUnwired, "error", {
342
+ body: message,
343
+ attributes: eventAttrs({
344
+ "senpi.runtime.id": runtimeId,
345
+ "senpi.strategy.address": wallet ? wallet.toLowerCase() : undefined,
346
+ "senpi.scanners.launch_phase": phase,
347
+ }),
348
+ });
349
+ apiLogger.error(message, error, {
350
+ "senpi.runtime.id": runtimeId,
351
+ "senpi.scanners.launch_phase": phase,
352
+ });
353
+ };
326
354
  const lifecycleChatId = resolveTelegramChatIdFromStore(senpiCliStore);
327
355
  const lifecycleNotifications = lifecycleChatId
328
356
  ? createNotificationService({
@@ -459,8 +487,14 @@ const senpiRuntimePlugin = {
459
487
  // Trace the sizing-relevant fields the narrowed request carries, so a
460
488
  // field dropped at this seam is visible instead of vanishing silently.
461
489
  apiLogger.debug(`[intake] ingest req signal_id=${signal.signal_id} scanner=${resolved.scannerName} asset=${signal.asset} direction=${signal.direction} marginPct=${signal.marginPct} leverage=${signal.leverage}`);
462
- void h
463
- .ingestExternalScannerData(request)
490
+ // Serialize dispatch behind the shared per-key lock (engine guard
491
+ // identity) so a same-scanner batch or overlapping POSTs ingest one
492
+ // at a time instead of the engine rejecting all but the first as
493
+ // UNAVAILABLE. Still void — the POST response never blocks on the
494
+ // trade, just on lock ordering.
495
+ const key = ingestDispatchKey(resolved.runtimeId, resolved.scannerName);
496
+ void ingestDispatchMutex
497
+ .withKeyLock(key, () => h.ingestExternalScannerData(request))
464
498
  .then(() => {
465
499
  apiLogger.info(`[intake] ingest ok signal_id=${signal.signal_id} scanner=${resolved.scannerName} asset=${signal.asset} scanner_id=${scannerId}`);
466
500
  })
@@ -523,8 +557,8 @@ const senpiRuntimePlugin = {
523
557
  }
524
558
  catch (mountErr) {
525
559
  // Mount failure is non-fatal: the runtime itself is already up.
526
- // Log and skip the launcher for this runtime.
527
- apiLogger.error("[senpi-runtime] scanner mount failed — runtime running without supervised scanners", { runtimeId: entry.id, err: mountErr });
560
+ // Event it and skip the launcher for this runtime.
561
+ eventScannersUnwired("mount", entry.id, entry.wallet, "[senpi-runtime] scanner mount failed — runtime running without supervised scanners", mountErr);
528
562
  }
529
563
  }
530
564
  }
@@ -603,7 +637,7 @@ const senpiRuntimePlugin = {
603
637
  catch (startErr) {
604
638
  await launcher.stop().catch(() => { });
605
639
  launchers.delete(id);
606
- apiLogger.error("[senpi-runtime] supervised scanner launch failed — runtime running without it", { err: startErr });
640
+ eventScannersUnwired("launch", id, runtimeHandles.get(id)?.wallet, "[senpi-runtime] supervised scanner launch failed — runtime running without it", startErr);
607
641
  }
608
642
  }
609
643
  }
@@ -649,13 +683,11 @@ const senpiRuntimePlugin = {
649
683
  runtimeHandles.delete(ids[i]);
650
684
  }
651
685
  pluginLogger.info("[senpi-runtime] All runtimes stopped");
652
- // Flush plugin-scoped telemetry (lifecycle.runtime.created/deleted); otherwise
653
- // BatchingTransport may still hold buffered events until the interval fires.
654
- await pluginEventTracker.shutdown().catch((err) => {
655
- pluginLogger.warn("[senpi-runtime] plugin telemetry shutdown failed", {
656
- err: err instanceof Error ? err.message : String(err),
657
- });
658
- });
686
+ // Final, process-global OTel SDK flush. Last step, after every runtime is
687
+ // stopped and all spans are emitted: we disabled HyperDX's own SIGTERM
688
+ // flush (stopOnTerminationSignals: false), so this is the only drain of the
689
+ // SDK's span/log buffers on exit.
690
+ await shutdownOtelSdk();
659
691
  },
660
692
  });
661
693
  pluginLogger.info("[senpi-runtime] calling api.registerCli(..., { commands: ['senpi'] })");
@@ -818,21 +850,6 @@ const senpiRuntimePlugin = {
818
850
  }
819
851
  registry.runtimes.push(entry);
820
852
  await writeRegistry(baseStateDir, registry);
821
- const createdMapping = BUS_EVENT_MAP["tracking.runtime_created"];
822
- pluginEventTracker.capture({
823
- eventType: createdMapping.eventType,
824
- category: createdMapping.category,
825
- address: wallet,
826
- data: {
827
- id: resolvedId,
828
- name: runtimeName,
829
- wallet,
830
- schemaVersion: parsedSchemaVersion,
831
- source: hasPath ? "file" : "inline",
832
- config: entry,
833
- timestamp: new Date().toISOString(),
834
- },
835
- });
836
853
  try {
837
854
  const scannerProviders = await createScannerProvidersForRun({
838
855
  mcpTransport,
@@ -848,6 +865,9 @@ const senpiRuntimePlugin = {
848
865
  runtimeId: resolvedId,
849
866
  });
850
867
  runtimeHandles.set(resolvedId, handle);
868
+ // Registry create fact — distinct from the runtime.started boot transition (which also fires
869
+ // on a transient restart). Emitted inside emitEvent's guard so telemetry never fails the install.
870
+ emitEvent(apiLogger, () => buildRuntimeCreatedEvent({ runtimeId: resolvedId, address: wallet, recipeName: runtimeName }));
851
871
  // ── hot-install supervised scanner wire ───────────────────────────────
852
872
  // Live-install path: used when a runtime is registered after boot via
853
873
  // senpi.installRuntime, while the API is already listening — the
@@ -888,13 +908,13 @@ const senpiRuntimePlugin = {
888
908
  }
889
909
  catch (startErr) {
890
910
  await hotLauncher.stop().catch(() => { });
891
- apiLogger.error("[senpi-runtime] hot-install supervised scanner launch failed — runtime running without it", { runtimeId: resolvedId, err: startErr });
911
+ eventScannersUnwired("install_launch", resolvedId, wallet, "[senpi-runtime] hot-install supervised scanner launch failed — runtime running without it", startErr);
892
912
  }
893
913
  }
894
914
  }
895
915
  catch (wireErr) {
896
916
  // Wire failure must NOT fail the install — the runtime is already up.
897
- apiLogger.error("[senpi-runtime] hot-install wiring failed — runtime running without supervised scanners", { runtimeId: resolvedId, err: wireErr });
917
+ eventScannersUnwired("install_wire", resolvedId, wallet, "[senpi-runtime] hot-install wiring failed — runtime running without supervised scanners", wireErr);
898
918
  }
899
919
  }
900
920
  // ──────────────────────────────────────────────────────────────────────
@@ -954,13 +974,8 @@ const senpiRuntimePlugin = {
954
974
  });
955
975
  return;
956
976
  }
957
- const targetWallet = deletedEntry?.wallet ??
958
- handle?.wallet ??
959
- (typeof targetAddress === "string" ? targetAddress : "");
960
- let openPositionsAbandoned = 0;
961
- let archivePath;
962
977
  if (handle) {
963
- openPositionsAbandoned = await handle.teardownDslForRuntimeDeletion();
978
+ await handle.teardownDslForRuntimeDeletion();
964
979
  await handle.stop();
965
980
  runtimeHandles.delete(targetId);
966
981
  }
@@ -977,32 +992,25 @@ const senpiRuntimePlugin = {
977
992
  const runtimeStateDir = buildRuntimeStateDir(baseStateDir, targetId, deletedEntry.wallet ?? "");
978
993
  const archivesDir = join(baseStateDir, "archives");
979
994
  try {
980
- archivePath = await archiveStateDir(runtimeStateDir, archivesDir, targetId, deletedEntry.wallet ?? "");
995
+ const archivePath = await archiveStateDir(runtimeStateDir, archivesDir, targetId, deletedEntry.wallet ?? "");
981
996
  api.logger.info(`[senpi-runtime] Archived state to ${archivePath}`);
982
997
  }
983
998
  catch (err) {
984
999
  api.logger.warn("[senpi-runtime] Failed to archive state dir", { err });
985
1000
  }
986
1001
  }
987
- const deletedMapping = BUS_EVENT_MAP["tracking.runtime_deleted"];
988
- pluginEventTracker.capture({
989
- eventType: deletedMapping.eventType,
990
- category: deletedMapping.category,
991
- address: targetWallet,
992
- data: {
993
- id: targetId,
994
- wallet: targetWallet,
995
- schemaVersion: deletedEntry?.schemaVersion,
996
- reason: "user_initiated",
997
- openPositionsAbandoned,
998
- ...(typeof archivePath === "string" ? { archivedAt: archivePath } : {}),
999
- timestamp: new Date().toISOString(),
1000
- },
1001
- });
1002
1002
  if (deletedEntry) {
1003
1003
  const next = registry.runtimes.filter((e) => e.id !== targetId);
1004
1004
  await writeRegistry(baseStateDir, { ...registry, runtimes: next });
1005
1005
  }
1006
+ // Registry delete fact — the permanent-removal discriminator a transient runtime.stopped can't
1007
+ // give. Unconditional (a never-booted runtime stops no handle, so emits no runtime.stopped) and
1008
+ // inside emitEvent's guard so telemetry never fails the delete.
1009
+ emitEvent(apiLogger, () => buildRuntimeDeletedEvent({
1010
+ runtimeId: targetId,
1011
+ address: deletedEntry?.wallet,
1012
+ hadLiveHandle: Boolean(handle),
1013
+ }));
1006
1014
  respond(true, { id: targetId });
1007
1015
  }, { scope: "operator.write" });
1008
1016
  /**
@@ -1225,7 +1233,9 @@ const senpiRuntimePlugin = {
1225
1233
  try {
1226
1234
  const state = await handle.getSystemState();
1227
1235
  respond(true, {
1228
- state: state ? { ...state, runtimeId } : null,
1236
+ state: state
1237
+ ? enrichScannerLiveness({ ...state, runtimeId }, sharedIntakeContext)
1238
+ : null,
1229
1239
  updater,
1230
1240
  });
1231
1241
  }
@@ -1238,7 +1248,7 @@ const senpiRuntimePlugin = {
1238
1248
  }
1239
1249
  return;
1240
1250
  }
1241
- const states = await collectRuntimeSystemStates(runtimeHandles, api.logger, baseStateDir);
1251
+ const states = (await collectRuntimeSystemStates(runtimeHandles, api.logger, baseStateDir)).map((s) => enrichScannerLiveness(s, sharedIntakeContext));
1242
1252
  respond(true, { states, updater });
1243
1253
  }, { scope: "operator.read" });
1244
1254
  /**
@@ -1391,6 +1401,157 @@ const senpiRuntimePlugin = {
1391
1401
  });
1392
1402
  }
1393
1403
  }, { scope: "operator.read" });
1404
+ // Backend trade-audit trail (MCP tool calls + AI reasoning), already
1405
+ // reachable on HTTP `/audit`. Passes through the caller-controlled subset
1406
+ // of the audit_query contract; resource scoping (wallet → strategyId) is
1407
+ // owned by handle.auditQuery, never the caller.
1408
+ api.registerGatewayMethod("senpi.auditQuery", async (ctx) => {
1409
+ const respond = ctx.respond;
1410
+ const runtimeId = typeof ctx.params?.runtimeId === "string" ? ctx.params.runtimeId : undefined;
1411
+ if (!runtimeId) {
1412
+ respond(false, undefined, { code: "INVALID_REQUEST", message: "runtimeId is required" });
1413
+ return;
1414
+ }
1415
+ const handle = getRuntimeHandleOrRespond(runtimeHandles, runtimeId, respond);
1416
+ if (!handle) {
1417
+ return;
1418
+ }
1419
+ const p = ctx.params ?? {};
1420
+ const args = {};
1421
+ if (typeof p.tool_name === "string")
1422
+ args.tool_name = p.tool_name;
1423
+ if (p.action_type === "read" || p.action_type === "create" || p.action_type === "update" || p.action_type === "delete") {
1424
+ args.action_type = p.action_type;
1425
+ }
1426
+ if (typeof p.success === "boolean")
1427
+ args.success = p.success;
1428
+ if (typeof p.start_time === "string")
1429
+ args.start_time = p.start_time;
1430
+ if (typeof p.end_time === "string")
1431
+ args.end_time = p.end_time;
1432
+ if (typeof p.limit === "number")
1433
+ args.limit = p.limit;
1434
+ if (typeof p.offset === "number")
1435
+ args.offset = p.offset;
1436
+ try {
1437
+ const result = await handle.auditQuery(args);
1438
+ respond(true, { result, strategyId: handle.getStrategyId() });
1439
+ }
1440
+ catch (err) {
1441
+ if (err instanceof AuditQueryError) {
1442
+ respond(false, undefined, { code: err.code, message: err.message });
1443
+ return;
1444
+ }
1445
+ api.logger.warn("[senpi-runtime] auditQuery error", { runtimeId, err });
1446
+ respond(false, undefined, {
1447
+ code: "INTERNAL_ERROR",
1448
+ message: `Failed to query audit trail: ${formatGatewayError(err)}`,
1449
+ });
1450
+ }
1451
+ }, { scope: "operator.read" });
1452
+ // Per-wallet risk gate-check audit log (on-disk JSONL). The Runtime keeps
1453
+ // its state root private, so re-derive it from baseStateDir + the handle's
1454
+ // wallet (same helper the writer's stateDir was built with); the writer
1455
+ // nests entries under `<root>/<address>/risk-guard/audit.jsonl`.
1456
+ api.registerGatewayMethod("senpi.getRiskAudit", async (ctx) => {
1457
+ const respond = ctx.respond;
1458
+ const runtimeId = typeof ctx.params?.runtimeId === "string" ? ctx.params.runtimeId : undefined;
1459
+ if (!runtimeId) {
1460
+ respond(false, undefined, { code: "INVALID_REQUEST", message: "runtimeId is required" });
1461
+ return;
1462
+ }
1463
+ const handle = getRuntimeHandleOrRespond(runtimeHandles, runtimeId, respond);
1464
+ if (!handle) {
1465
+ return;
1466
+ }
1467
+ const resolvedAddress = typeof ctx.params?.address === "string" && ctx.params.address.length > 0
1468
+ ? ctx.params.address
1469
+ : handle.wallet;
1470
+ if (!resolvedAddress) {
1471
+ respond(false, undefined, {
1472
+ code: "INVALID_REQUEST",
1473
+ message: "address is required when the runtime wallet is unknown",
1474
+ });
1475
+ return;
1476
+ }
1477
+ // Path safety: the address builds the on-disk audit path; reject a non-wallet before the read.
1478
+ if (!isWalletAddress(resolvedAddress)) {
1479
+ respond(false, undefined, { code: "INVALID_REQUEST", message: "address is not a valid wallet" });
1480
+ return;
1481
+ }
1482
+ const limit = typeof ctx.params?.limit === "number" && ctx.params.limit > 0 ? ctx.params.limit : 100;
1483
+ const stateDir = buildRuntimeStateDir(baseStateDir, runtimeId, handle.wallet ?? "");
1484
+ try {
1485
+ const entries = await readRiskAuditEntries(stateDir, resolvedAddress, limit);
1486
+ respond(true, { entries, address: resolvedAddress });
1487
+ }
1488
+ catch (err) {
1489
+ api.logger.warn("[senpi-runtime] getRiskAudit error", { runtimeId, err });
1490
+ respond(false, undefined, {
1491
+ code: "INTERNAL_ERROR",
1492
+ message: `Failed to read risk audit: ${formatGatewayError(err)}`,
1493
+ });
1494
+ }
1495
+ }, { scope: "operator.read" });
1496
+ // Per-strategy local domain-event ring (on-disk JSONL) — the trade narrative, queryable locally.
1497
+ // Same state-root re-derivation as getRiskAudit: the Runtime keeps its root private, so rebuild it
1498
+ // from baseStateDir + the handle's wallet; the writer nests rows under `<root>/strategies/<address>/events/`.
1499
+ api.registerGatewayMethod("senpi.getEvents", async (ctx) => {
1500
+ const respond = ctx.respond;
1501
+ const runtimeId = typeof ctx.params?.runtimeId === "string" ? ctx.params.runtimeId : undefined;
1502
+ if (!runtimeId) {
1503
+ respond(false, undefined, { code: "INVALID_REQUEST", message: "runtimeId is required" });
1504
+ return;
1505
+ }
1506
+ const handle = getRuntimeHandleOrRespond(runtimeHandles, runtimeId, respond);
1507
+ if (!handle) {
1508
+ return;
1509
+ }
1510
+ const p = ctx.params ?? {};
1511
+ const resolvedAddress = typeof p.address === "string" && p.address.length > 0 ? p.address : handle.wallet;
1512
+ if (!resolvedAddress) {
1513
+ respond(false, undefined, {
1514
+ code: "INVALID_REQUEST",
1515
+ message: "address is required when the runtime wallet is unknown",
1516
+ });
1517
+ return;
1518
+ }
1519
+ // Path safety: the address builds the on-disk events path; reject a non-wallet before the read.
1520
+ if (!isWalletAddress(resolvedAddress)) {
1521
+ respond(false, undefined, { code: "INVALID_REQUEST", message: "address is not a valid wallet" });
1522
+ return;
1523
+ }
1524
+ const query = {};
1525
+ if (typeof p.name === "string")
1526
+ query.name = p.name;
1527
+ if (typeof p.asset === "string")
1528
+ query.asset = p.asset;
1529
+ if (p.level === "debug" || p.level === "info" || p.level === "warn" || p.level === "error") {
1530
+ query.level = p.level;
1531
+ }
1532
+ // ISO 8601 (or epoch-ms) time bounds → epoch ms; Date.parse returns NaN (not undefined) on
1533
+ // unparseable input, so Number.isFinite is the carry — no separate undefined check needed.
1534
+ const sinceMs = typeof p.since === "string" ? Date.parse(p.since) : NaN;
1535
+ if (Number.isFinite(sinceMs))
1536
+ query.sinceMs = sinceMs;
1537
+ const untilMs = typeof p.until === "string" ? Date.parse(p.until) : NaN;
1538
+ if (Number.isFinite(untilMs))
1539
+ query.untilMs = untilMs;
1540
+ if (typeof p.limit === "number" && p.limit > 0)
1541
+ query.limit = p.limit;
1542
+ const stateDir = buildRuntimeStateDir(baseStateDir, runtimeId, handle.wallet ?? "");
1543
+ try {
1544
+ const entries = await readEvents(stateDir, resolvedAddress, query);
1545
+ respond(true, { entries, address: resolvedAddress });
1546
+ }
1547
+ catch (err) {
1548
+ api.logger.warn("[senpi-runtime] getEvents error", { runtimeId, err });
1549
+ respond(false, undefined, {
1550
+ code: "INTERNAL_ERROR",
1551
+ message: `Failed to read events: ${formatGatewayError(err)}`,
1552
+ });
1553
+ }
1554
+ }, { scope: "operator.read" });
1394
1555
  // ─── Skills manager — read + mutate ──────────────────────────────────────
1395
1556
  api.registerGatewayMethod("senpi.skills.status", async (ctx) => {
1396
1557
  const respond = ctx.respond;
@@ -1505,6 +1666,30 @@ async function collectRuntimeHealthStatuses(runtimeHandles, logger) {
1505
1666
  }
1506
1667
  }))).filter((status) => status !== null);
1507
1668
  }
1669
+ /**
1670
+ * Stamps external-scanner `lastAliveAt` onto the scanners component from the shared intake
1671
+ * liveness clock. Liveness is keyed by the ephemeral scanner_id; the registry resolves it back
1672
+ * to the stable scanner name (which matches the system-state row's scannerId). Interval/internal
1673
+ * scanners never POST, so they keep the module's `null`. Mutates the freshly-built rows in place.
1674
+ */
1675
+ function enrichScannerLiveness(state, intake) {
1676
+ const rows = state.components?.scanners?.state?.scanners;
1677
+ if (!intake || !Array.isArray(rows) || rows.length === 0) {
1678
+ return state;
1679
+ }
1680
+ const liveByName = new Map();
1681
+ for (const entry of intake.registry.entries()) {
1682
+ if (entry.runtimeId === state.runtimeId) {
1683
+ liveByName.set(entry.scannerName, intake.liveness.lastAliveAt(entry.scannerId));
1684
+ }
1685
+ }
1686
+ for (const row of rows) {
1687
+ if (row.scheduleMode === "external") {
1688
+ row.lastAliveAt = liveByName.get(row.scannerId) ?? null;
1689
+ }
1690
+ }
1691
+ return state;
1692
+ }
1508
1693
  async function collectRuntimeSystemStates(runtimeHandles, logger, baseStateDir) {
1509
1694
  return (await Promise.all(Array.from(runtimeHandles, async ([runtimeId, handle]) => {
1510
1695
  try {