@invinite-org/chartlang-runtime 1.1.1 → 1.3.0

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 (294) hide show
  1. package/CHANGELOG.md +307 -0
  2. package/dist/barPoint.d.ts +20 -0
  3. package/dist/barPoint.d.ts.map +1 -0
  4. package/dist/barPoint.js +72 -0
  5. package/dist/barPoint.js.map +1 -0
  6. package/dist/bufferSnapshot.d.ts +102 -0
  7. package/dist/bufferSnapshot.d.ts.map +1 -0
  8. package/dist/bufferSnapshot.js +119 -0
  9. package/dist/bufferSnapshot.js.map +1 -0
  10. package/dist/buildComputeContext.d.ts.map +1 -1
  11. package/dist/buildComputeContext.js +6 -1
  12. package/dist/buildComputeContext.js.map +1 -1
  13. package/dist/createScriptRunner.d.ts +6 -3
  14. package/dist/createScriptRunner.d.ts.map +1 -1
  15. package/dist/createScriptRunner.js +65 -11
  16. package/dist/createScriptRunner.js.map +1 -1
  17. package/dist/dep/DepRunner.d.ts +7 -0
  18. package/dist/dep/DepRunner.d.ts.map +1 -1
  19. package/dist/dep/DepRunner.js +4 -0
  20. package/dist/dep/DepRunner.js.map +1 -1
  21. package/dist/emit/barcolor.d.ts +44 -0
  22. package/dist/emit/barcolor.d.ts.map +1 -0
  23. package/dist/emit/barcolor.js +40 -0
  24. package/dist/emit/barcolor.js.map +1 -0
  25. package/dist/emit/bgcolor.d.ts +44 -0
  26. package/dist/emit/bgcolor.d.ts.map +1 -0
  27. package/dist/emit/bgcolor.js +45 -0
  28. package/dist/emit/bgcolor.js.map +1 -0
  29. package/dist/emit/draw/boxes/fillBetween.d.ts +45 -0
  30. package/dist/emit/draw/boxes/fillBetween.d.ts.map +1 -0
  31. package/dist/emit/draw/boxes/fillBetween.js +36 -0
  32. package/dist/emit/draw/boxes/fillBetween.js.map +1 -0
  33. package/dist/emit/draw/handle.d.ts +9 -0
  34. package/dist/emit/draw/handle.d.ts.map +1 -1
  35. package/dist/emit/draw/handle.js +65 -10
  36. package/dist/emit/draw/handle.js.map +1 -1
  37. package/dist/emit/draw/namespace.d.ts +4 -3
  38. package/dist/emit/draw/namespace.d.ts.map +1 -1
  39. package/dist/emit/draw/namespace.js +6 -3
  40. package/dist/emit/draw/namespace.js.map +1 -1
  41. package/dist/emit/index.d.ts +2 -0
  42. package/dist/emit/index.d.ts.map +1 -1
  43. package/dist/emit/index.js +2 -0
  44. package/dist/emit/index.js.map +1 -1
  45. package/dist/emit/plot.d.ts +30 -1
  46. package/dist/emit/plot.d.ts.map +1 -1
  47. package/dist/emit/plot.js +45 -1
  48. package/dist/emit/plot.js.map +1 -1
  49. package/dist/execution/dispose.d.ts.map +1 -1
  50. package/dist/execution/dispose.js +18 -0
  51. package/dist/execution/dispose.js.map +1 -1
  52. package/dist/execution/runComputeStep.d.ts.map +1 -1
  53. package/dist/execution/runComputeStep.js +12 -1
  54. package/dist/execution/runComputeStep.js.map +1 -1
  55. package/dist/index.d.ts +1 -1
  56. package/dist/index.d.ts.map +1 -1
  57. package/dist/index.js +1 -1
  58. package/dist/index.js.map +1 -1
  59. package/dist/inputs/resolveInputs.js +1 -0
  60. package/dist/inputs/resolveInputs.js.map +1 -1
  61. package/dist/persistentStateStore.runtime.d.ts.map +1 -1
  62. package/dist/persistentStateStore.runtime.js +26 -7
  63. package/dist/persistentStateStore.runtime.js.map +1 -1
  64. package/dist/primitives.d.ts +1 -1
  65. package/dist/primitives.d.ts.map +1 -1
  66. package/dist/primitives.js +7 -1
  67. package/dist/primitives.js.map +1 -1
  68. package/dist/request/index.d.ts +2 -1
  69. package/dist/request/index.d.ts.map +1 -1
  70. package/dist/request/index.js +2 -1
  71. package/dist/request/index.js.map +1 -1
  72. package/dist/request/lowerTf.d.ts.map +1 -1
  73. package/dist/request/lowerTf.js +6 -0
  74. package/dist/request/lowerTf.js.map +1 -1
  75. package/dist/request/requestNamespace.d.ts.map +1 -1
  76. package/dist/request/requestNamespace.js +30 -3
  77. package/dist/request/requestNamespace.js.map +1 -1
  78. package/dist/request/security.d.ts +40 -4
  79. package/dist/request/security.d.ts.map +1 -1
  80. package/dist/request/security.js +114 -40
  81. package/dist/request/security.js.map +1 -1
  82. package/dist/request/securityExprRunner.d.ts +137 -0
  83. package/dist/request/securityExprRunner.d.ts.map +1 -0
  84. package/dist/request/securityExprRunner.js +253 -0
  85. package/dist/request/securityExprRunner.js.map +1 -0
  86. package/dist/request/streamBars.d.ts +14 -1
  87. package/dist/request/streamBars.d.ts.map +1 -1
  88. package/dist/request/streamBars.js +39 -1
  89. package/dist/request/streamBars.js.map +1 -1
  90. package/dist/ringBuffer.d.ts +19 -0
  91. package/dist/ringBuffer.d.ts.map +1 -1
  92. package/dist/ringBuffer.js +23 -0
  93. package/dist/ringBuffer.js.map +1 -1
  94. package/dist/runtimeContext.d.ts +90 -5
  95. package/dist/runtimeContext.d.ts.map +1 -1
  96. package/dist/runtimeContext.js.map +1 -1
  97. package/dist/seriesView.d.ts +42 -17
  98. package/dist/seriesView.d.ts.map +1 -1
  99. package/dist/seriesView.js +65 -42
  100. package/dist/seriesView.js.map +1 -1
  101. package/dist/state/arrayPersistence.d.ts +48 -0
  102. package/dist/state/arrayPersistence.d.ts.map +1 -0
  103. package/dist/state/arrayPersistence.js +88 -0
  104. package/dist/state/arrayPersistence.js.map +1 -0
  105. package/dist/state/arrayStateSlot.d.ts +78 -0
  106. package/dist/state/arrayStateSlot.d.ts.map +1 -0
  107. package/dist/state/arrayStateSlot.js +116 -0
  108. package/dist/state/arrayStateSlot.js.map +1 -0
  109. package/dist/state/index.d.ts +4 -1
  110. package/dist/state/index.d.ts.map +1 -1
  111. package/dist/state/index.js +4 -1
  112. package/dist/state/index.js.map +1 -1
  113. package/dist/state/lifecycle.d.ts +68 -0
  114. package/dist/state/lifecycle.d.ts.map +1 -1
  115. package/dist/state/lifecycle.js +89 -0
  116. package/dist/state/lifecycle.js.map +1 -1
  117. package/dist/state/seriesPersistence.d.ts +48 -0
  118. package/dist/state/seriesPersistence.d.ts.map +1 -0
  119. package/dist/state/seriesPersistence.js +87 -0
  120. package/dist/state/seriesPersistence.js.map +1 -0
  121. package/dist/state/seriesSlot.d.ts +105 -0
  122. package/dist/state/seriesSlot.d.ts.map +1 -0
  123. package/dist/state/seriesSlot.js +123 -0
  124. package/dist/state/seriesSlot.js.map +1 -0
  125. package/dist/state/stateNamespace.d.ts.map +1 -1
  126. package/dist/state/stateNamespace.js +55 -0
  127. package/dist/state/stateNamespace.js.map +1 -1
  128. package/dist/streamState.d.ts +25 -19
  129. package/dist/streamState.d.ts.map +1 -1
  130. package/dist/streamState.js +40 -66
  131. package/dist/streamState.js.map +1 -1
  132. package/dist/ta/adx.d.ts +3 -2
  133. package/dist/ta/adx.d.ts.map +1 -1
  134. package/dist/ta/adx.js +3 -2
  135. package/dist/ta/adx.js.map +1 -1
  136. package/dist/ta/alma.d.ts +6 -4
  137. package/dist/ta/alma.d.ts.map +1 -1
  138. package/dist/ta/alma.js +19 -6
  139. package/dist/ta/alma.js.map +1 -1
  140. package/dist/ta/atr.d.ts +3 -2
  141. package/dist/ta/atr.d.ts.map +1 -1
  142. package/dist/ta/atr.js +3 -2
  143. package/dist/ta/atr.js.map +1 -1
  144. package/dist/ta/bb.d.ts +3 -2
  145. package/dist/ta/bb.d.ts.map +1 -1
  146. package/dist/ta/bb.js +3 -2
  147. package/dist/ta/bb.js.map +1 -1
  148. package/dist/ta/chaikinOsc.d.ts +3 -2
  149. package/dist/ta/chaikinOsc.d.ts.map +1 -1
  150. package/dist/ta/chaikinOsc.js +3 -2
  151. package/dist/ta/chaikinOsc.js.map +1 -1
  152. package/dist/ta/crossover.d.ts +3 -2
  153. package/dist/ta/crossover.d.ts.map +1 -1
  154. package/dist/ta/crossover.js +3 -2
  155. package/dist/ta/crossover.js.map +1 -1
  156. package/dist/ta/crossunder.d.ts +3 -2
  157. package/dist/ta/crossunder.d.ts.map +1 -1
  158. package/dist/ta/crossunder.js +3 -2
  159. package/dist/ta/crossunder.js.map +1 -1
  160. package/dist/ta/dmi.d.ts +4 -3
  161. package/dist/ta/dmi.d.ts.map +1 -1
  162. package/dist/ta/dmi.js +4 -3
  163. package/dist/ta/dmi.js.map +1 -1
  164. package/dist/ta/ema.d.ts +3 -2
  165. package/dist/ta/ema.d.ts.map +1 -1
  166. package/dist/ta/ema.js +3 -2
  167. package/dist/ta/ema.js.map +1 -1
  168. package/dist/ta/eom.d.ts +3 -1
  169. package/dist/ta/eom.d.ts.map +1 -1
  170. package/dist/ta/eom.js +3 -1
  171. package/dist/ta/eom.js.map +1 -1
  172. package/dist/ta/highestbars.d.ts +25 -0
  173. package/dist/ta/highestbars.d.ts.map +1 -0
  174. package/dist/ta/highestbars.js +106 -0
  175. package/dist/ta/highestbars.js.map +1 -0
  176. package/dist/ta/historicalVolatility.d.ts +3 -2
  177. package/dist/ta/historicalVolatility.d.ts.map +1 -1
  178. package/dist/ta/historicalVolatility.js +3 -2
  179. package/dist/ta/historicalVolatility.js.map +1 -1
  180. package/dist/ta/ichimoku.d.ts +3 -1
  181. package/dist/ta/ichimoku.d.ts.map +1 -1
  182. package/dist/ta/ichimoku.js +3 -1
  183. package/dist/ta/ichimoku.js.map +1 -1
  184. package/dist/ta/lowestbars.d.ts +25 -0
  185. package/dist/ta/lowestbars.d.ts.map +1 -0
  186. package/dist/ta/lowestbars.js +102 -0
  187. package/dist/ta/lowestbars.js.map +1 -0
  188. package/dist/ta/macd.d.ts +3 -2
  189. package/dist/ta/macd.d.ts.map +1 -1
  190. package/dist/ta/macd.js +3 -2
  191. package/dist/ta/macd.js.map +1 -1
  192. package/dist/ta/massIndex.d.ts +3 -2
  193. package/dist/ta/massIndex.d.ts.map +1 -1
  194. package/dist/ta/massIndex.js +3 -2
  195. package/dist/ta/massIndex.js.map +1 -1
  196. package/dist/ta/mfi.d.ts +3 -1
  197. package/dist/ta/mfi.d.ts.map +1 -1
  198. package/dist/ta/mfi.js +3 -1
  199. package/dist/ta/mfi.js.map +1 -1
  200. package/dist/ta/netVolume.d.ts +3 -1
  201. package/dist/ta/netVolume.d.ts.map +1 -1
  202. package/dist/ta/netVolume.js +3 -1
  203. package/dist/ta/netVolume.js.map +1 -1
  204. package/dist/ta/nvi.d.ts +3 -1
  205. package/dist/ta/nvi.d.ts.map +1 -1
  206. package/dist/ta/nvi.js +3 -1
  207. package/dist/ta/nvi.js.map +1 -1
  208. package/dist/ta/persistence.d.ts.map +1 -1
  209. package/dist/ta/persistence.js +1 -40
  210. package/dist/ta/persistence.js.map +1 -1
  211. package/dist/ta/ppo.d.ts +3 -2
  212. package/dist/ta/ppo.d.ts.map +1 -1
  213. package/dist/ta/ppo.js +3 -2
  214. package/dist/ta/ppo.js.map +1 -1
  215. package/dist/ta/pvi.d.ts +3 -1
  216. package/dist/ta/pvi.d.ts.map +1 -1
  217. package/dist/ta/pvi.js +3 -1
  218. package/dist/ta/pvi.js.map +1 -1
  219. package/dist/ta/pvo.d.ts +3 -1
  220. package/dist/ta/pvo.d.ts.map +1 -1
  221. package/dist/ta/pvo.js +3 -1
  222. package/dist/ta/pvo.js.map +1 -1
  223. package/dist/ta/pvt.d.ts +3 -1
  224. package/dist/ta/pvt.d.ts.map +1 -1
  225. package/dist/ta/pvt.js +3 -1
  226. package/dist/ta/pvt.js.map +1 -1
  227. package/dist/ta/registry.d.ts +7 -1
  228. package/dist/ta/registry.d.ts.map +1 -1
  229. package/dist/ta/registry.js +4 -0
  230. package/dist/ta/registry.js.map +1 -1
  231. package/dist/ta/rsi.d.ts +3 -2
  232. package/dist/ta/rsi.d.ts.map +1 -1
  233. package/dist/ta/rsi.js +3 -2
  234. package/dist/ta/rsi.js.map +1 -1
  235. package/dist/ta/rvi.d.ts +3 -2
  236. package/dist/ta/rvi.d.ts.map +1 -1
  237. package/dist/ta/rvi.js +3 -2
  238. package/dist/ta/rvi.js.map +1 -1
  239. package/dist/ta/sessionVolumeProfile.d.ts.map +1 -1
  240. package/dist/ta/sessionVolumeProfile.js +1 -17
  241. package/dist/ta/sessionVolumeProfile.js.map +1 -1
  242. package/dist/ta/sma.d.ts +6 -3
  243. package/dist/ta/sma.d.ts.map +1 -1
  244. package/dist/ta/sma.js +6 -3
  245. package/dist/ta/sma.js.map +1 -1
  246. package/dist/ta/stdev.d.ts +3 -2
  247. package/dist/ta/stdev.d.ts.map +1 -1
  248. package/dist/ta/stdev.js +3 -2
  249. package/dist/ta/stdev.js.map +1 -1
  250. package/dist/ta/trendStrengthIndex.d.ts +3 -2
  251. package/dist/ta/trendStrengthIndex.d.ts.map +1 -1
  252. package/dist/ta/trendStrengthIndex.js +3 -2
  253. package/dist/ta/trendStrengthIndex.js.map +1 -1
  254. package/dist/ta/trix.d.ts +4 -3
  255. package/dist/ta/trix.d.ts.map +1 -1
  256. package/dist/ta/trix.js +4 -3
  257. package/dist/ta/trix.js.map +1 -1
  258. package/dist/ta/vortex.d.ts +3 -2
  259. package/dist/ta/vortex.d.ts.map +1 -1
  260. package/dist/ta/vortex.js +3 -2
  261. package/dist/ta/vortex.js.map +1 -1
  262. package/dist/time-accessors/civil.d.ts +73 -0
  263. package/dist/time-accessors/civil.d.ts.map +1 -0
  264. package/dist/time-accessors/civil.js +105 -0
  265. package/dist/time-accessors/civil.js.map +1 -0
  266. package/dist/time-accessors/index.d.ts +8 -0
  267. package/dist/time-accessors/index.d.ts.map +1 -0
  268. package/dist/time-accessors/index.js +9 -0
  269. package/dist/time-accessors/index.js.map +1 -0
  270. package/dist/time-accessors/sessionAccessors.d.ts +50 -0
  271. package/dist/time-accessors/sessionAccessors.d.ts.map +1 -0
  272. package/dist/time-accessors/sessionAccessors.js +79 -0
  273. package/dist/time-accessors/sessionAccessors.js.map +1 -0
  274. package/dist/time-accessors/sessionWindow.d.ts +17 -0
  275. package/dist/time-accessors/sessionWindow.d.ts.map +1 -0
  276. package/dist/time-accessors/sessionWindow.js +41 -0
  277. package/dist/time-accessors/sessionWindow.js.map +1 -0
  278. package/dist/time-accessors/timeAccessors.d.ts +54 -0
  279. package/dist/time-accessors/timeAccessors.d.ts.map +1 -0
  280. package/dist/time-accessors/timeAccessors.js +132 -0
  281. package/dist/time-accessors/timeAccessors.js.map +1 -0
  282. package/dist/time-accessors/tzDiagnostic.d.ts +17 -0
  283. package/dist/time-accessors/tzDiagnostic.d.ts.map +1 -0
  284. package/dist/time-accessors/tzDiagnostic.js +34 -0
  285. package/dist/time-accessors/tzDiagnostic.js.map +1 -0
  286. package/dist/time-accessors/tzOffset.d.ts +31 -0
  287. package/dist/time-accessors/tzOffset.d.ts.map +1 -0
  288. package/dist/time-accessors/tzOffset.js +67 -0
  289. package/dist/time-accessors/tzOffset.js.map +1 -0
  290. package/package.json +3 -3
  291. package/dist/ta/lib/applyOffset.d.ts +0 -19
  292. package/dist/ta/lib/applyOffset.d.ts.map +0 -1
  293. package/dist/ta/lib/applyOffset.js +0 -38
  294. package/dist/ta/lib/applyOffset.js.map +0 -1
@@ -1 +1 @@
1
- {"version":3,"file":"persistentStateStore.runtime.js","sourceRoot":"","sources":["../src/persistentStateStore.runtime.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright (c) 2026 Invinite. Licensed under the MIT License.\n// See the LICENSE file in the repo root for full license text.\n\nimport type {\n JsonValue,\n RunnerSnapshot,\n StateSnapshot,\n StreamSnapshot,\n} from \"@invinite-org/chartlang-core\";\n\nimport type { RunnerState } from \"./createScriptRunner.js\";\nimport { pushDiagnostic } from \"./emit/index.js\";\nimport { validateSnapshot } from \"./persistentStateStore.validate.js\";\nimport type { RuntimeContext } from \"./runtimeContext.js\";\nimport { restoreStateSlots, serialiseStateSlots } from \"./state/index.js\";\nimport { isTaSlotSnapshotKey, restoreTaSlots, serialiseTaSlots } from \"./ta/persistence.js\";\n\n/**\n * Default PLAN §6.9 write cadence for persistent snapshots.\n *\n * @since 0.5\n * @internal\n * @example\n * const stale = Date.now() - PERSISTENCE_INTERVAL_MS;\n * void stale;\n */\nexport const PERSISTENCE_INTERVAL_MS = 60_000;\n\nfunction firstStreamKey(snapshot: StateSnapshot): string | null {\n const entries = Object.entries(snapshot.streams);\n const first = entries[0];\n return first === undefined ? null : first[0];\n}\n\nfunction captureStreams(state: RunnerState): Readonly<Record<string, StreamSnapshot>> {\n const main = state.mainStream.serialiseSnapshot();\n const streams: Record<string, StreamSnapshot> = {\n [main.interval === \"\" ? \"main\" : main.interval]: main,\n };\n for (const [key, stream] of state.runtimeContext.secondaryStreams) {\n streams[key] = stream.serialiseSnapshot();\n }\n return Object.freeze(streams);\n}\n\nfunction primarySectionSlots(state: RunnerState): Readonly<Record<string, JsonValue>> {\n return Object.freeze({\n ...serialiseStateSlots(state.runtimeContext),\n ...serialiseTaSlots(state.mainStream),\n } as Record<string, JsonValue>);\n}\n\nfunction runnerSection(ctx: RuntimeContext): RunnerSnapshot {\n return Object.freeze({\n slots: Object.freeze({ ...serialiseStateSlots(ctx) } as Record<string, JsonValue>),\n });\n}\n\nfunction captureSiblings(state: RunnerState): Readonly<Record<string, RunnerSnapshot>> | undefined {\n if (state.siblingRunners.length === 0) return undefined;\n const out: Record<string, RunnerSnapshot> = {};\n for (const sibling of state.siblingRunners) {\n out[sibling.exportName] = runnerSection(sibling.state.runtimeContext);\n }\n return Object.freeze(out);\n}\n\nfunction captureDependencies(\n state: RunnerState,\n): Readonly<Record<string, RunnerSnapshot>> | undefined {\n if (state.depRunners.length === 0) return undefined;\n const out: Record<string, RunnerSnapshot> = {};\n for (const dep of state.depRunners) {\n out[dep.localId] = runnerSection(dep.state.runtimeContext);\n }\n return Object.freeze(out);\n}\n\n/**\n * Capture the runner's current stream + per-runner state-slot snapshot.\n *\n * Returns the structured shape carrying `primary.slots`, optional\n * `siblings[exportName].slots`, and optional `dependencies[localId].slots`.\n * TA slots live in `primary.slots` because the bundle's deps and siblings\n * share the primary's `mainStream` (Task-4 invariant).\n *\n * @since 0.5 — widened to per-runner sections in 0.7.\n * @internal\n * @example\n * // const snapshot = captureStateSnapshot(state, Date.now());\n * const captured = true;\n * void captured;\n */\nexport function captureStateSnapshot(state: RunnerState, savedAt: number): StateSnapshot | null {\n const streams = captureStreams(state);\n const siblings = captureSiblings(state);\n const dependencies = captureDependencies(state);\n const candidate: StateSnapshot = {\n lastBarTime: state.mainStream.bar.time,\n streams,\n savedAt,\n snapshotVersion: 1,\n primary: { slots: primarySectionSlots(state) },\n ...(siblings === undefined ? {} : { siblings }),\n ...(dependencies === undefined ? {} : { dependencies }),\n };\n if (!validateSnapshot(candidate)) return null;\n return candidate;\n}\n\n// Phase-1 mounts have `bar.interval === \"\"` until the first bar lands; in that\n// window the snapshot is keyed by whatever captureStreams used (\"main\" or the\n// explicit interval). Fall back to the snapshot's first-entered stream so warm\n// restart still finds the buffer.\nfunction resolveMainStreamSnapshot(\n snapshot: StateSnapshot,\n mainInterval: string,\n): StreamSnapshot | undefined {\n const direct = mainInterval === \"\" ? undefined : snapshot.streams[mainInterval];\n if (direct !== undefined) return direct;\n const fallback = firstStreamKey(snapshot);\n return fallback === null ? undefined : snapshot.streams[fallback];\n}\n\nfunction nonTaSlots(slots: Readonly<Record<string, JsonValue>>): Record<string, unknown> {\n const out: Record<string, unknown> = {};\n for (const [slotKey, value] of Object.entries(slots)) {\n if (!isTaSlotSnapshotKey(slotKey)) {\n out[slotKey] = value;\n }\n }\n return out;\n}\n\nfunction pushMalformedSection(state: RunnerState, message: string): void {\n pushDiagnostic(state.emissions, {\n kind: \"diagnostic\",\n severity: \"warning\",\n code: \"state-snapshot-malformed\",\n message,\n slotId: null,\n bar: state.barIndex,\n });\n}\n\nfunction restoreSiblingSections(\n state: RunnerState,\n siblings: Readonly<Record<string, RunnerSnapshot>>,\n): void {\n const lookup = new Map(state.siblingRunners.map((sib) => [sib.exportName, sib]));\n for (const [exportName, section] of Object.entries(siblings)) {\n const sibling = lookup.get(exportName);\n if (sibling === undefined) {\n pushMalformedSection(\n state,\n `persistent state snapshot referenced unknown sibling \"${exportName}\"`,\n );\n continue;\n }\n restoreStateSlots(sibling.state.runtimeContext, section.slots);\n }\n}\n\nfunction restoreDependencySections(\n state: RunnerState,\n dependencies: Readonly<Record<string, RunnerSnapshot>>,\n): void {\n const lookup = new Map(state.depRunners.map((dep) => [dep.localId, dep]));\n for (const [localId, section] of Object.entries(dependencies)) {\n const dep = lookup.get(localId);\n if (dep === undefined) {\n pushMalformedSection(\n state,\n `persistent state snapshot referenced unknown dependency \"${localId}\"`,\n );\n continue;\n }\n restoreStateSlots(dep.state.runtimeContext, section.slots);\n }\n}\n\n/**\n * Restore a validated snapshot into the runner's stream + slot stores.\n *\n * Walks every per-runner section: `primary.slots` rehydrates the\n * primary's `state.*` slots (and TA slots on the shared mainStream);\n * `siblings[exportName].slots` and `dependencies[localId].slots`\n * rehydrate each matching sub-runner. Snapshot sections whose id is not\n * declared by the current bundle are skipped with a\n * `state-snapshot-malformed` diagnostic.\n *\n * Legacy flat-shape snapshots (pre-0.7) restore into the primary only.\n *\n * @since 0.5 — widened to per-runner sections in 0.7.\n * @internal\n * @example\n * // restoreStateSnapshot(state, snapshot);\n * const restored = true;\n * void restored;\n */\nexport function restoreStateSnapshot(state: RunnerState, snapshot: StateSnapshot): void {\n const stream = resolveMainStreamSnapshot(snapshot, state.mainStream.bar.interval);\n if (stream !== undefined) {\n state.mainStream.restoreFromSnapshot(stream);\n state.barIndex = Math.max(state.barIndex, stream.filled);\n }\n for (const [secondaryKey, secondary] of state.runtimeContext.secondaryStreams) {\n const secondarySnapshot = snapshot.streams[secondaryKey];\n if (secondarySnapshot !== undefined) {\n secondary.restoreFromSnapshot(secondarySnapshot);\n }\n }\n\n const primarySlots = primarySlotsOf(snapshot);\n restoreTaSlots(state.mainStream, primarySlots);\n restoreStateSlots(state.runtimeContext, nonTaSlots(primarySlots));\n\n if (snapshot.siblings !== undefined) {\n restoreSiblingSections(state, snapshot.siblings);\n }\n if (snapshot.dependencies !== undefined) {\n restoreDependencySections(state, snapshot.dependencies);\n }\n}\n\n/**\n * Resolve the primary runner's slot map from either the structured shape\n * (`snapshot.primary.slots`) or the legacy flat shape (`snapshot.slots`).\n * The validator accepts both but the strict `StateSnapshot` type only\n * mirrors the structured shape; the dual shape is read through this\n * legacy-aware view. {@link validateSnapshot} guarantees at least one of\n * the two shapes is present so we never fall through.\n *\n * @internal\n */\ntype LegacySnapshotView = Readonly<{\n readonly primary?: RunnerSnapshot;\n readonly slots?: Readonly<Record<string, JsonValue>>;\n}>;\n\nconst EMPTY_SLOTS: Readonly<Record<string, JsonValue>> = Object.freeze({});\n\nfunction primarySlotsOf(snapshot: StateSnapshot): Readonly<Record<string, JsonValue>> {\n const view = snapshot as LegacySnapshotView;\n if (view.primary !== undefined) return view.primary.slots;\n /* c8 ignore next 2 — validateSnapshot guarantees one of primary/slots is present. */\n if (view.slots === undefined) return EMPTY_SLOTS;\n return view.slots;\n}\n\n/**\n * Save one snapshot and convert malformed/save failures into diagnostics.\n *\n * @since 0.5\n * @internal\n * @example\n * // await saveStateSnapshot(state, Date.now());\n * const saved = true;\n * void saved;\n */\nexport async function saveStateSnapshot(state: RunnerState, savedAt: number): Promise<boolean> {\n const store = state.runtimeContext.persistentStateStore;\n if (store === undefined) return false;\n const snapshot = captureStateSnapshot(state, savedAt);\n if (snapshot === null) {\n pushDiagnostic(state.emissions, {\n kind: \"diagnostic\",\n severity: \"warning\",\n code: \"state-snapshot-malformed\",\n message: \"persistent state snapshot was not JSON-clean\",\n slotId: null,\n bar: state.barIndex,\n });\n return false;\n }\n try {\n await store.save(snapshot);\n state.runtimeContext.lastPersistTime = savedAt;\n return true;\n } catch (err) {\n pushDiagnostic(state.emissions, {\n kind: \"diagnostic\",\n severity: \"warning\",\n code: \"state-snapshot-save-failed\",\n message: err instanceof Error ? err.message : String(err),\n slotId: null,\n bar: state.barIndex,\n });\n return false;\n }\n}\n\n/**\n * Save when the configured PLAN §6.9 wall-clock cadence is stale.\n *\n * @since 0.5\n * @internal\n * @example\n * // await maybeSaveStateSnapshot(state, Date.now(), 60_000);\n * const maybe = true;\n * void maybe;\n */\nexport async function maybeSaveStateSnapshot(\n state: RunnerState,\n savedAt: number,\n intervalMs: number,\n): Promise<void> {\n if (state.runtimeContext.persistentStateStore === undefined) return;\n if (savedAt - state.runtimeContext.lastPersistTime >= intervalMs) {\n await saveStateSnapshot(state, savedAt);\n }\n}\n"]}
1
+ {"version":3,"file":"persistentStateStore.runtime.js","sourceRoot":"","sources":["../src/persistentStateStore.runtime.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright (c) 2026 Invinite. Licensed under the MIT License.\n// See the LICENSE file in the repo root for full license text.\n\nimport type {\n JsonValue,\n RunnerSnapshot,\n StateSnapshot,\n StreamSnapshot,\n} from \"@invinite-org/chartlang-core\";\n\nimport type { RunnerState } from \"./createScriptRunner.js\";\nimport { pushDiagnostic } from \"./emit/index.js\";\nimport { validateSnapshot } from \"./persistentStateStore.validate.js\";\nimport type { RuntimeContext } from \"./runtimeContext.js\";\nimport {\n isArraySlotSnapshotKey,\n isSeriesSlotSnapshotKey,\n restoreArraySlots,\n restoreSeriesSlots,\n restoreStateSlots,\n serialiseArraySlots,\n serialiseSeriesSlots,\n serialiseStateSlots,\n} from \"./state/index.js\";\nimport { isTaSlotSnapshotKey, restoreTaSlots, serialiseTaSlots } from \"./ta/persistence.js\";\n\n/**\n * Default PLAN §6.9 write cadence for persistent snapshots.\n *\n * @since 0.5\n * @internal\n * @example\n * const stale = Date.now() - PERSISTENCE_INTERVAL_MS;\n * void stale;\n */\nexport const PERSISTENCE_INTERVAL_MS = 60_000;\n\nfunction firstStreamKey(snapshot: StateSnapshot): string | null {\n const entries = Object.entries(snapshot.streams);\n const first = entries[0];\n return first === undefined ? null : first[0];\n}\n\nfunction captureStreams(state: RunnerState): Readonly<Record<string, StreamSnapshot>> {\n const main = state.mainStream.serialiseSnapshot();\n const streams: Record<string, StreamSnapshot> = {\n [main.interval === \"\" ? \"main\" : main.interval]: main,\n };\n for (const [key, stream] of state.runtimeContext.secondaryStreams) {\n streams[key] = stream.serialiseSnapshot();\n }\n return Object.freeze(streams);\n}\n\nfunction primarySectionSlots(state: RunnerState): Readonly<Record<string, JsonValue>> {\n return Object.freeze({\n ...serialiseStateSlots(state.runtimeContext),\n ...serialiseSeriesSlots(state.runtimeContext),\n ...serialiseArraySlots(state.runtimeContext),\n ...serialiseTaSlots(state.mainStream),\n } as Record<string, JsonValue>);\n}\n\nfunction runnerSection(ctx: RuntimeContext): RunnerSnapshot {\n return Object.freeze({\n slots: Object.freeze({\n ...serialiseStateSlots(ctx),\n ...serialiseSeriesSlots(ctx),\n ...serialiseArraySlots(ctx),\n } as Record<string, JsonValue>),\n });\n}\n\nfunction captureSiblings(state: RunnerState): Readonly<Record<string, RunnerSnapshot>> | undefined {\n if (state.siblingRunners.length === 0) return undefined;\n const out: Record<string, RunnerSnapshot> = {};\n for (const sibling of state.siblingRunners) {\n out[sibling.exportName] = runnerSection(sibling.state.runtimeContext);\n }\n return Object.freeze(out);\n}\n\nfunction captureDependencies(\n state: RunnerState,\n): Readonly<Record<string, RunnerSnapshot>> | undefined {\n if (state.depRunners.length === 0) return undefined;\n const out: Record<string, RunnerSnapshot> = {};\n for (const dep of state.depRunners) {\n out[dep.localId] = runnerSection(dep.state.runtimeContext);\n }\n return Object.freeze(out);\n}\n\n/**\n * Capture the runner's current stream + per-runner state-slot snapshot.\n *\n * Returns the structured shape carrying `primary.slots`, optional\n * `siblings[exportName].slots`, and optional `dependencies[localId].slots`.\n * TA slots live in `primary.slots` because the bundle's deps and siblings\n * share the primary's `mainStream` (Task-4 invariant).\n *\n * @since 0.5 — widened to per-runner sections in 0.7.\n * @internal\n * @example\n * // const snapshot = captureStateSnapshot(state, Date.now());\n * const captured = true;\n * void captured;\n */\nexport function captureStateSnapshot(state: RunnerState, savedAt: number): StateSnapshot | null {\n const streams = captureStreams(state);\n const siblings = captureSiblings(state);\n const dependencies = captureDependencies(state);\n const candidate: StateSnapshot = {\n lastBarTime: state.mainStream.bar.time,\n streams,\n savedAt,\n snapshotVersion: 1,\n primary: { slots: primarySectionSlots(state) },\n ...(siblings === undefined ? {} : { siblings }),\n ...(dependencies === undefined ? {} : { dependencies }),\n };\n if (!validateSnapshot(candidate)) return null;\n return candidate;\n}\n\n// Phase-1 mounts have `bar.interval === \"\"` until the first bar lands; in that\n// window the snapshot is keyed by whatever captureStreams used (\"main\" or the\n// explicit interval). Fall back to the snapshot's first-entered stream so warm\n// restart still finds the buffer.\nfunction resolveMainStreamSnapshot(\n snapshot: StateSnapshot,\n mainInterval: string,\n): StreamSnapshot | undefined {\n const direct = mainInterval === \"\" ? undefined : snapshot.streams[mainInterval];\n if (direct !== undefined) return direct;\n const fallback = firstStreamKey(snapshot);\n return fallback === null ? undefined : snapshot.streams[fallback];\n}\n\n// Scalar `state.*` keys only — strip `ta:` (restored onto the stream),\n// `:series` (restored into `ctx.seriesSlots`), and `:array` (restored into\n// `ctx.arraySlots`) so the scalar slot store receives none of them.\nfunction scalarStateSlots(slots: Readonly<Record<string, unknown>>): Record<string, unknown> {\n const out: Record<string, unknown> = {};\n for (const [slotKey, value] of Object.entries(slots)) {\n if (\n !isTaSlotSnapshotKey(slotKey) &&\n !isSeriesSlotSnapshotKey(slotKey) &&\n !isArraySlotSnapshotKey(slotKey)\n ) {\n out[slotKey] = value;\n }\n }\n return out;\n}\n\n// Restore a runner's scalar `state.*` slots and `state.series` slots from\n// one merged `slots` record. Series rings are sized to the runner's current\n// ring capacity (the close buffer's capacity).\nfunction restoreRunnerSlots(\n ctx: RuntimeContext,\n slots: Readonly<Record<string, unknown>>,\n capacity: number,\n): void {\n restoreStateSlots(ctx, scalarStateSlots(slots));\n restoreSeriesSlots(ctx, slots, capacity);\n restoreArraySlots(ctx, slots);\n}\n\nfunction pushMalformedSection(state: RunnerState, message: string): void {\n pushDiagnostic(state.emissions, {\n kind: \"diagnostic\",\n severity: \"warning\",\n code: \"state-snapshot-malformed\",\n message,\n slotId: null,\n bar: state.barIndex,\n });\n}\n\nfunction restoreSiblingSections(\n state: RunnerState,\n siblings: Readonly<Record<string, RunnerSnapshot>>,\n): void {\n const lookup = new Map(state.siblingRunners.map((sib) => [sib.exportName, sib]));\n for (const [exportName, section] of Object.entries(siblings)) {\n const sibling = lookup.get(exportName);\n if (sibling === undefined) {\n pushMalformedSection(\n state,\n `persistent state snapshot referenced unknown sibling \"${exportName}\"`,\n );\n continue;\n }\n restoreRunnerSlots(\n sibling.state.runtimeContext,\n section.slots,\n state.mainStream.ohlcv.close.capacity,\n );\n }\n}\n\nfunction restoreDependencySections(\n state: RunnerState,\n dependencies: Readonly<Record<string, RunnerSnapshot>>,\n): void {\n const lookup = new Map(state.depRunners.map((dep) => [dep.localId, dep]));\n for (const [localId, section] of Object.entries(dependencies)) {\n const dep = lookup.get(localId);\n if (dep === undefined) {\n pushMalformedSection(\n state,\n `persistent state snapshot referenced unknown dependency \"${localId}\"`,\n );\n continue;\n }\n restoreRunnerSlots(\n dep.state.runtimeContext,\n section.slots,\n state.mainStream.ohlcv.close.capacity,\n );\n }\n}\n\n/**\n * Restore a validated snapshot into the runner's stream + slot stores.\n *\n * Walks every per-runner section: `primary.slots` rehydrates the\n * primary's `state.*` slots (and TA slots on the shared mainStream);\n * `siblings[exportName].slots` and `dependencies[localId].slots`\n * rehydrate each matching sub-runner. Snapshot sections whose id is not\n * declared by the current bundle are skipped with a\n * `state-snapshot-malformed` diagnostic.\n *\n * Legacy flat-shape snapshots (pre-0.7) restore into the primary only.\n *\n * @since 0.5 — widened to per-runner sections in 0.7.\n * @internal\n * @example\n * // restoreStateSnapshot(state, snapshot);\n * const restored = true;\n * void restored;\n */\nexport function restoreStateSnapshot(state: RunnerState, snapshot: StateSnapshot): void {\n const stream = resolveMainStreamSnapshot(snapshot, state.mainStream.bar.interval);\n if (stream !== undefined) {\n state.mainStream.restoreFromSnapshot(stream);\n state.barIndex = Math.max(state.barIndex, stream.filled);\n }\n for (const [secondaryKey, secondary] of state.runtimeContext.secondaryStreams) {\n const secondarySnapshot = snapshot.streams[secondaryKey];\n if (secondarySnapshot !== undefined) {\n secondary.restoreFromSnapshot(secondarySnapshot);\n }\n }\n\n const primarySlots = primarySlotsOf(snapshot);\n restoreTaSlots(state.mainStream, primarySlots);\n restoreRunnerSlots(state.runtimeContext, primarySlots, state.mainStream.ohlcv.close.capacity);\n\n if (snapshot.siblings !== undefined) {\n restoreSiblingSections(state, snapshot.siblings);\n }\n if (snapshot.dependencies !== undefined) {\n restoreDependencySections(state, snapshot.dependencies);\n }\n}\n\n/**\n * Resolve the primary runner's slot map from either the structured shape\n * (`snapshot.primary.slots`) or the legacy flat shape (`snapshot.slots`).\n * The validator accepts both but the strict `StateSnapshot` type only\n * mirrors the structured shape; the dual shape is read through this\n * legacy-aware view. {@link validateSnapshot} guarantees at least one of\n * the two shapes is present so we never fall through.\n *\n * @internal\n */\ntype LegacySnapshotView = Readonly<{\n readonly primary?: RunnerSnapshot;\n readonly slots?: Readonly<Record<string, JsonValue>>;\n}>;\n\nconst EMPTY_SLOTS: Readonly<Record<string, JsonValue>> = Object.freeze({});\n\nfunction primarySlotsOf(snapshot: StateSnapshot): Readonly<Record<string, JsonValue>> {\n const view = snapshot as LegacySnapshotView;\n if (view.primary !== undefined) return view.primary.slots;\n /* c8 ignore next 2 — validateSnapshot guarantees one of primary/slots is present. */\n if (view.slots === undefined) return EMPTY_SLOTS;\n return view.slots;\n}\n\n/**\n * Save one snapshot and convert malformed/save failures into diagnostics.\n *\n * @since 0.5\n * @internal\n * @example\n * // await saveStateSnapshot(state, Date.now());\n * const saved = true;\n * void saved;\n */\nexport async function saveStateSnapshot(state: RunnerState, savedAt: number): Promise<boolean> {\n const store = state.runtimeContext.persistentStateStore;\n if (store === undefined) return false;\n const snapshot = captureStateSnapshot(state, savedAt);\n if (snapshot === null) {\n pushDiagnostic(state.emissions, {\n kind: \"diagnostic\",\n severity: \"warning\",\n code: \"state-snapshot-malformed\",\n message: \"persistent state snapshot was not JSON-clean\",\n slotId: null,\n bar: state.barIndex,\n });\n return false;\n }\n try {\n await store.save(snapshot);\n state.runtimeContext.lastPersistTime = savedAt;\n return true;\n } catch (err) {\n pushDiagnostic(state.emissions, {\n kind: \"diagnostic\",\n severity: \"warning\",\n code: \"state-snapshot-save-failed\",\n message: err instanceof Error ? err.message : String(err),\n slotId: null,\n bar: state.barIndex,\n });\n return false;\n }\n}\n\n/**\n * Save when the configured PLAN §6.9 wall-clock cadence is stale.\n *\n * @since 0.5\n * @internal\n * @example\n * // await maybeSaveStateSnapshot(state, Date.now(), 60_000);\n * const maybe = true;\n * void maybe;\n */\nexport async function maybeSaveStateSnapshot(\n state: RunnerState,\n savedAt: number,\n intervalMs: number,\n): Promise<void> {\n if (state.runtimeContext.persistentStateStore === undefined) return;\n if (savedAt - state.runtimeContext.lastPersistTime >= intervalMs) {\n await saveStateSnapshot(state, savedAt);\n }\n}\n"]}
@@ -19,5 +19,5 @@ import type { TaNamespace } from "@invinite-org/chartlang-core";
19
19
  * // type S = typeof ta;
20
20
  */
21
21
  export declare const ta: TaNamespace;
22
- export { alert, draw, hline, plot } from "./emit/index.js";
22
+ export { alert, barcolor, bgcolor, draw, hline, plot } from "./emit/index.js";
23
23
  //# sourceMappingURL=primitives.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"primitives.d.ts","sourceRoot":"","sources":["../src/primitives.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,8BAA8B,CAAC;AAIhE;;;;;;;;;;;;;;;;;;GAkBG;AACH,eAAO,MAAM,EAAE,EAAE,WAAmD,CAAC;AAErE,OAAO,EAAE,KAAK,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,MAAM,iBAAiB,CAAC"}
1
+ {"version":3,"file":"primitives.d.ts","sourceRoot":"","sources":["../src/primitives.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,8BAA8B,CAAC;AAIhE;;;;;;;;;;;;;;;;;;GAkBG;AACH,eAAO,MAAM,EAAE,EAAE,WAAmD,CAAC;AAErE,OAAO,EAAE,KAAK,EAAE,QAAQ,EAAE,OAAO,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,MAAM,iBAAiB,CAAC"}
@@ -21,5 +21,11 @@ import { TA_REGISTRY } from "./ta/index.js";
21
21
  * // type S = typeof ta;
22
22
  */
23
23
  export const ta = TA_REGISTRY;
24
- export { alert, draw, hline, plot } from "./emit/index.js";
24
+ export { alert, barcolor, bgcolor, draw, hline, plot } from "./emit/index.js";
25
+ // `time` and `session` are the real UTC/fixed-offset calendar namespaces, built
26
+ // per-mount by `buildComputeContext.ts` via `buildTimeNamespace(ctx)` /
27
+ // `buildSessionNamespace(ctx)` — neither can be a module-level constant like
28
+ // `ta` because both close over the mount's `ctx` (default tz from
29
+ // `syminfo.timezone` + the shared `tz-dst-unsupported` dedup). The core
30
+ // `session` sentinel hole is no longer re-exported here.
25
31
  //# sourceMappingURL=primitives.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"primitives.js","sourceRoot":"","sources":["../src/primitives.ts"],"names":[],"mappings":"AAAA,+DAA+D;AAC/D,+DAA+D;AAI/D,OAAO,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAE5C;;;;;;;;;;;;;;;;;;GAkBG;AACH,MAAM,CAAC,MAAM,EAAE,GAAgB,WAAqC,CAAC;AAErE,OAAO,EAAE,KAAK,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,MAAM,iBAAiB,CAAC","sourcesContent":["// Copyright (c) 2026 Invinite. Licensed under the MIT License.\n// See the LICENSE file in the repo root for full license text.\n\nimport type { TaNamespace } from \"@invinite-org/chartlang-core\";\n\nimport { TA_REGISTRY } from \"./ta/index.js\";\n\n/**\n * The runtime's `ta` namespace as the compiled script sees it. Task 6's\n * `createScriptRunner` puts this on the `ComputeContext` it hands the\n * compiled script; Task 7 swapped the body from a throw-stub to the\n * real {@link TA_REGISTRY} (`./ta/registry`). Identity is preserved\n * across the swap — `buildComputeContext.ts` still imports `ta` from\n * here and the runner contract from Task 6 stays untouched.\n *\n * The runtime impls take a compiler-injected `slotId` as their first\n * argument; the compiler erases the extra arg at the type boundary so\n * `ComputeContext.ta: TaNamespace` (script-facing) and the bundled call\n * `ta.ema(\"slot-id\", src, length)` are structurally compatible at\n * runtime.\n *\n * @since 0.1\n * @example\n * // import { ta } from \"@invinite-org/chartlang-runtime\";\n * // type S = typeof ta;\n */\nexport const ta: TaNamespace = TA_REGISTRY as unknown as TaNamespace;\n\nexport { alert, draw, hline, plot } from \"./emit/index.js\";\n"]}
1
+ {"version":3,"file":"primitives.js","sourceRoot":"","sources":["../src/primitives.ts"],"names":[],"mappings":"AAAA,+DAA+D;AAC/D,+DAA+D;AAI/D,OAAO,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAE5C;;;;;;;;;;;;;;;;;;GAkBG;AACH,MAAM,CAAC,MAAM,EAAE,GAAgB,WAAqC,CAAC;AAErE,OAAO,EAAE,KAAK,EAAE,QAAQ,EAAE,OAAO,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,MAAM,iBAAiB,CAAC;AAC9E,gFAAgF;AAChF,wEAAwE;AACxE,6EAA6E;AAC7E,kEAAkE;AAClE,wEAAwE;AACxE,yDAAyD","sourcesContent":["// Copyright (c) 2026 Invinite. Licensed under the MIT License.\n// See the LICENSE file in the repo root for full license text.\n\nimport type { TaNamespace } from \"@invinite-org/chartlang-core\";\n\nimport { TA_REGISTRY } from \"./ta/index.js\";\n\n/**\n * The runtime's `ta` namespace as the compiled script sees it. Task 6's\n * `createScriptRunner` puts this on the `ComputeContext` it hands the\n * compiled script; Task 7 swapped the body from a throw-stub to the\n * real {@link TA_REGISTRY} (`./ta/registry`). Identity is preserved\n * across the swap — `buildComputeContext.ts` still imports `ta` from\n * here and the runner contract from Task 6 stays untouched.\n *\n * The runtime impls take a compiler-injected `slotId` as their first\n * argument; the compiler erases the extra arg at the type boundary so\n * `ComputeContext.ta: TaNamespace` (script-facing) and the bundled call\n * `ta.ema(\"slot-id\", src, length)` are structurally compatible at\n * runtime.\n *\n * @since 0.1\n * @example\n * // import { ta } from \"@invinite-org/chartlang-runtime\";\n * // type S = typeof ta;\n */\nexport const ta: TaNamespace = TA_REGISTRY as unknown as TaNamespace;\n\nexport { alert, barcolor, bgcolor, draw, hline, plot } from \"./emit/index.js\";\n// `time` and `session` are the real UTC/fixed-offset calendar namespaces, built\n// per-mount by `buildComputeContext.ts` via `buildTimeNamespace(ctx)` /\n// `buildSessionNamespace(ctx)` — neither can be a module-level constant like\n// `ta` because both close over the mount's `ctx` (default tz from\n// `syminfo.timezone` + the shared `tz-dst-unsupported` dedup). The core\n// `session` sentinel hole is no longer re-exported here.\n"]}
@@ -1,4 +1,5 @@
1
1
  export { buildRequestNamespace } from "./requestNamespace.js";
2
2
  export { makeLowerTfSeries } from "./lowerTf.js";
3
- export { makeNanSecurityBar, makeSecurityBar } from "./security.js";
3
+ export { makeNanSecurityBar, makeSecurityBar, makeSecurityExprSeries } from "./security.js";
4
+ export { type SecurityExprRegistry, type SecurityExprRunner, ascendingValues, buildSecurityExprRunners, captureAndCatchUp, createSecurityExprRunner, driveSecurityExpressions, } from "./securityExprRunner.js";
4
5
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/request/index.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,qBAAqB,EAAE,MAAM,uBAAuB,CAAC;AAC9D,OAAO,EAAE,iBAAiB,EAAE,MAAM,cAAc,CAAC;AACjD,OAAO,EAAE,kBAAkB,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/request/index.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,qBAAqB,EAAE,MAAM,uBAAuB,CAAC;AAC9D,OAAO,EAAE,iBAAiB,EAAE,MAAM,cAAc,CAAC;AACjD,OAAO,EAAE,kBAAkB,EAAE,eAAe,EAAE,sBAAsB,EAAE,MAAM,eAAe,CAAC;AAC5F,OAAO,EACH,KAAK,oBAAoB,EACzB,KAAK,kBAAkB,EACvB,eAAe,EACf,wBAAwB,EACxB,iBAAiB,EACjB,wBAAwB,EACxB,wBAAwB,GAC3B,MAAM,yBAAyB,CAAC"}
@@ -2,5 +2,6 @@
2
2
  // See the LICENSE file in the repo root for full license text.
3
3
  export { buildRequestNamespace } from "./requestNamespace.js";
4
4
  export { makeLowerTfSeries } from "./lowerTf.js";
5
- export { makeNanSecurityBar, makeSecurityBar } from "./security.js";
5
+ export { makeNanSecurityBar, makeSecurityBar, makeSecurityExprSeries } from "./security.js";
6
+ export { ascendingValues, buildSecurityExprRunners, captureAndCatchUp, createSecurityExprRunner, driveSecurityExpressions, } from "./securityExprRunner.js";
6
7
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/request/index.ts"],"names":[],"mappings":"AAAA,+DAA+D;AAC/D,+DAA+D;AAE/D,OAAO,EAAE,qBAAqB,EAAE,MAAM,uBAAuB,CAAC;AAC9D,OAAO,EAAE,iBAAiB,EAAE,MAAM,cAAc,CAAC;AACjD,OAAO,EAAE,kBAAkB,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC","sourcesContent":["// Copyright (c) 2026 Invinite. Licensed under the MIT License.\n// See the LICENSE file in the repo root for full license text.\n\nexport { buildRequestNamespace } from \"./requestNamespace.js\";\nexport { makeLowerTfSeries } from \"./lowerTf.js\";\nexport { makeNanSecurityBar, makeSecurityBar } from \"./security.js\";\n"]}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/request/index.ts"],"names":[],"mappings":"AAAA,+DAA+D;AAC/D,+DAA+D;AAE/D,OAAO,EAAE,qBAAqB,EAAE,MAAM,uBAAuB,CAAC;AAC9D,OAAO,EAAE,iBAAiB,EAAE,MAAM,cAAc,CAAC;AACjD,OAAO,EAAE,kBAAkB,EAAE,eAAe,EAAE,sBAAsB,EAAE,MAAM,eAAe,CAAC;AAC5F,OAAO,EAGH,eAAe,EACf,wBAAwB,EACxB,iBAAiB,EACjB,wBAAwB,EACxB,wBAAwB,GAC3B,MAAM,yBAAyB,CAAC","sourcesContent":["// Copyright (c) 2026 Invinite. Licensed under the MIT License.\n// See the LICENSE file in the repo root for full license text.\n\nexport { buildRequestNamespace } from \"./requestNamespace.js\";\nexport { makeLowerTfSeries } from \"./lowerTf.js\";\nexport { makeNanSecurityBar, makeSecurityBar, makeSecurityExprSeries } from \"./security.js\";\nexport {\n type SecurityExprRegistry,\n type SecurityExprRunner,\n ascendingValues,\n buildSecurityExprRunners,\n captureAndCatchUp,\n createSecurityExprRunner,\n driveSecurityExpressions,\n} from \"./securityExprRunner.js\";\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"lowerTf.d.ts","sourceRoot":"","sources":["../../src/request/lowerTf.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,EAAE,MAAM,8BAA8B,CAAC;AAEhE,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AA+D3D;;;;;;;;;GASG;AACH,wBAAgB,iBAAiB,CAC7B,GAAG,EAAE,cAAc,EACnB,MAAM,EAAE,MAAM,EACd,QAAQ,EAAE,MAAM,GACjB,MAAM,CAAC,aAAa,CAAC,GAAG,CAAC,CAAC,CAwB5B"}
1
+ {"version":3,"file":"lowerTf.d.ts","sourceRoot":"","sources":["../../src/request/lowerTf.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,EAAE,MAAM,8BAA8B,CAAC;AAEhE,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AAqE3D;;;;;;;;;GASG;AACH,wBAAgB,iBAAiB,CAC7B,GAAG,EAAE,cAAc,EACnB,MAAM,EAAE,MAAM,EACd,QAAQ,EAAE,MAAM,GACjB,MAAM,CAAC,aAAa,CAAC,GAAG,CAAC,CAAC,CAwB5B"}
@@ -16,6 +16,12 @@ function bucketAt(ctx, slotId, interval, age) {
16
16
  if (!known) {
17
17
  return fallback(ctx, slotId, interval, "unsupported-interval", `Requested interval "${interval}" is not in Capabilities.intervals`);
18
18
  }
19
+ // `request.lowerTf` is chart-symbol-only (per-feed symbol is a deferred
20
+ // follow-up), so the bare interval IS the feed key — `feedKey(undefined,
21
+ // interval) === interval`. Keying the (feed-keyed) `secondaryStreams` map
22
+ // and the cache below by the bare interval is therefore byte-identical to
23
+ // routing through `feedKey`; if `lowerTf` ever gains a symbol, switch both
24
+ // sites to `feedKey(symbol, interval)` so they cannot silently mis-key.
19
25
  const secondary = ctx.secondaryStreams.get(interval);
20
26
  if (secondary === undefined) {
21
27
  return fallback(ctx, slotId, interval, "unknown-secondary-stream", `Requested interval "${interval}" has no registered secondary stream`);
@@ -1 +1 @@
1
- {"version":3,"file":"lowerTf.js","sourceRoot":"","sources":["../../src/request/lowerTf.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright (c) 2026 Invinite. Licensed under the MIT License.\n// See the LICENSE file in the repo root for full license text.\n\nimport type { Bar, Series } from \"@invinite-org/chartlang-core\";\n\nimport type { RuntimeContext } from \"../runtimeContext.js\";\nimport { getOrBucket } from \"./bucketLtfBarsCache.js\";\nimport { pushOnce } from \"./pushOnce.js\";\nimport { ascendingBarsFor } from \"./streamBars.js\";\n\nconst EMPTY_BUCKET: ReadonlyArray<Bar> = Object.freeze([]);\n\nfunction fallback(\n ctx: RuntimeContext,\n slotId: string,\n interval: string,\n code: \"unsupported-interval\" | \"multi-timeframe-not-supported\" | \"unknown-secondary-stream\",\n message: string,\n): ReadonlyArray<Bar> {\n pushOnce(ctx, code, slotId, interval, \"lowerTf\", message);\n return EMPTY_BUCKET;\n}\n\nfunction bucketAt(\n ctx: RuntimeContext,\n slotId: string,\n interval: string,\n age: number,\n): ReadonlyArray<Bar> {\n if (!ctx.capabilities.multiTimeframe) {\n return fallback(\n ctx,\n slotId,\n interval,\n \"multi-timeframe-not-supported\",\n \"Adapter declares multiTimeframe: false; request.lowerTf returns empty buckets\",\n );\n }\n\n const known = ctx.capabilities.intervals.some((descriptor) => descriptor.value === interval);\n if (!known) {\n return fallback(\n ctx,\n slotId,\n interval,\n \"unsupported-interval\",\n `Requested interval \"${interval}\" is not in Capabilities.intervals`,\n );\n }\n\n const secondary = ctx.secondaryStreams.get(interval);\n if (secondary === undefined) {\n return fallback(\n ctx,\n slotId,\n interval,\n \"unknown-secondary-stream\",\n `Requested interval \"${interval}\" has no registered secondary stream`,\n );\n }\n\n const mainBars = ascendingBarsFor(ctx, ctx.stream);\n const ltfBars = ascendingBarsFor(ctx, secondary);\n const buckets = getOrBucket(mainBars, ltfBars);\n const index = buckets.length - 1 - age;\n return buckets[index] ?? EMPTY_BUCKET;\n}\n\n/**\n * Return a stable series view of lower-timeframe buckets for a callsite.\n *\n * @since 0.6\n * @stable\n * @example\n * // const series = makeLowerTfSeries(ctx, \"slot#0\", \"30s\");\n * const requested = \"30s\";\n * void requested;\n */\nexport function makeLowerTfSeries(\n ctx: RuntimeContext,\n slotId: string,\n interval: string,\n): Series<ReadonlyArray<Bar>> {\n const cacheKey = `${slotId}|${interval}`;\n const existing = ctx.requestLowerTfViews.get(cacheKey);\n if (existing !== undefined) return existing;\n\n const target = {\n get current() {\n return bucketAt(ctx, slotId, interval, 0);\n },\n get length() {\n return ctx.stream.ohlcv.close.length;\n },\n };\n const view = new Proxy(Object.freeze(target), {\n get(obj, prop, receiver) {\n if (typeof prop === \"string\") {\n const n = Number(prop);\n if (Number.isInteger(n) && n >= 0) return bucketAt(ctx, slotId, interval, n);\n }\n return Reflect.get(obj, prop, receiver);\n },\n }) as Series<ReadonlyArray<Bar>>;\n ctx.requestLowerTfViews.set(cacheKey, view);\n return view;\n}\n"]}
1
+ {"version":3,"file":"lowerTf.js","sourceRoot":"","sources":["../../src/request/lowerTf.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright (c) 2026 Invinite. Licensed under the MIT License.\n// See the LICENSE file in the repo root for full license text.\n\nimport type { Bar, Series } from \"@invinite-org/chartlang-core\";\n\nimport type { RuntimeContext } from \"../runtimeContext.js\";\nimport { getOrBucket } from \"./bucketLtfBarsCache.js\";\nimport { pushOnce } from \"./pushOnce.js\";\nimport { ascendingBarsFor } from \"./streamBars.js\";\n\nconst EMPTY_BUCKET: ReadonlyArray<Bar> = Object.freeze([]);\n\nfunction fallback(\n ctx: RuntimeContext,\n slotId: string,\n interval: string,\n code: \"unsupported-interval\" | \"multi-timeframe-not-supported\" | \"unknown-secondary-stream\",\n message: string,\n): ReadonlyArray<Bar> {\n pushOnce(ctx, code, slotId, interval, \"lowerTf\", message);\n return EMPTY_BUCKET;\n}\n\nfunction bucketAt(\n ctx: RuntimeContext,\n slotId: string,\n interval: string,\n age: number,\n): ReadonlyArray<Bar> {\n if (!ctx.capabilities.multiTimeframe) {\n return fallback(\n ctx,\n slotId,\n interval,\n \"multi-timeframe-not-supported\",\n \"Adapter declares multiTimeframe: false; request.lowerTf returns empty buckets\",\n );\n }\n\n const known = ctx.capabilities.intervals.some((descriptor) => descriptor.value === interval);\n if (!known) {\n return fallback(\n ctx,\n slotId,\n interval,\n \"unsupported-interval\",\n `Requested interval \"${interval}\" is not in Capabilities.intervals`,\n );\n }\n\n // `request.lowerTf` is chart-symbol-only (per-feed symbol is a deferred\n // follow-up), so the bare interval IS the feed key — `feedKey(undefined,\n // interval) === interval`. Keying the (feed-keyed) `secondaryStreams` map\n // and the cache below by the bare interval is therefore byte-identical to\n // routing through `feedKey`; if `lowerTf` ever gains a symbol, switch both\n // sites to `feedKey(symbol, interval)` so they cannot silently mis-key.\n const secondary = ctx.secondaryStreams.get(interval);\n if (secondary === undefined) {\n return fallback(\n ctx,\n slotId,\n interval,\n \"unknown-secondary-stream\",\n `Requested interval \"${interval}\" has no registered secondary stream`,\n );\n }\n\n const mainBars = ascendingBarsFor(ctx, ctx.stream);\n const ltfBars = ascendingBarsFor(ctx, secondary);\n const buckets = getOrBucket(mainBars, ltfBars);\n const index = buckets.length - 1 - age;\n return buckets[index] ?? EMPTY_BUCKET;\n}\n\n/**\n * Return a stable series view of lower-timeframe buckets for a callsite.\n *\n * @since 0.6\n * @stable\n * @example\n * // const series = makeLowerTfSeries(ctx, \"slot#0\", \"30s\");\n * const requested = \"30s\";\n * void requested;\n */\nexport function makeLowerTfSeries(\n ctx: RuntimeContext,\n slotId: string,\n interval: string,\n): Series<ReadonlyArray<Bar>> {\n const cacheKey = `${slotId}|${interval}`;\n const existing = ctx.requestLowerTfViews.get(cacheKey);\n if (existing !== undefined) return existing;\n\n const target = {\n get current() {\n return bucketAt(ctx, slotId, interval, 0);\n },\n get length() {\n return ctx.stream.ohlcv.close.length;\n },\n };\n const view = new Proxy(Object.freeze(target), {\n get(obj, prop, receiver) {\n if (typeof prop === \"string\") {\n const n = Number(prop);\n if (Number.isInteger(n) && n >= 0) return bucketAt(ctx, slotId, interval, n);\n }\n return Reflect.get(obj, prop, receiver);\n },\n }) as Series<ReadonlyArray<Bar>>;\n ctx.requestLowerTfViews.set(cacheKey, view);\n return view;\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"requestNamespace.d.ts","sourceRoot":"","sources":["../../src/request/requestNamespace.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAGR,gBAAgB,EAInB,MAAM,8BAA8B,CAAC;AAwBtC;;;;;;;;;;;;;GAaG;AACH,wBAAgB,qBAAqB,IAAI,gBAAgB,CAGxD"}
1
+ {"version":3,"file":"requestNamespace.d.ts","sourceRoot":"","sources":["../../src/request/requestNamespace.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAGR,gBAAgB,EAKnB,MAAM,8BAA8B,CAAC;AAuDtC;;;;;;;;;;;;;GAaG;AACH,wBAAgB,qBAAqB,IAAI,gBAAgB,CAGxD"}
@@ -1,8 +1,10 @@
1
1
  // Copyright (c) 2026 Invinite. Licensed under the MIT License.
2
2
  // See the LICENSE file in the repo root for full license text.
3
+ import { feedKey } from "@invinite-org/chartlang-core";
3
4
  import { ACTIVE_RUNTIME_CONTEXT } from "../runtimeContext.js";
4
5
  import { makeLowerTfSeries } from "./lowerTf.js";
5
- import { makeSecurityBar } from "./security.js";
6
+ import { makeSecurityBar, makeSecurityExprSeries } from "./security.js";
7
+ import { captureAndCatchUp } from "./securityExprRunner.js";
6
8
  function getCtx(name) {
7
9
  const ctx = ACTIVE_RUNTIME_CONTEXT.current;
8
10
  if (ctx === null) {
@@ -10,9 +12,34 @@ function getCtx(name) {
10
12
  }
11
13
  return ctx;
12
14
  }
13
- function security(slotId, opts) {
15
+ // Resolve a requested symbol to the value the secondary stream is keyed under.
16
+ // An omitted symbol — or the chart's own ticker passed explicitly — collapses
17
+ // to `undefined` so `feedKey` produces the bare interval, hitting the same
18
+ // stream as the omitted-symbol form (no duplicate) and staying byte-identical
19
+ // to the pre-multi-symbol baseline. Only a *different* symbol survives as the
20
+ // `"<symbol>@<interval>"` feed.
21
+ function resolveSymbol(ctx, symbol) {
22
+ return symbol === undefined || symbol === ctx.chartSymbol ? undefined : symbol;
23
+ }
24
+ // Dispatch off the runner registry (not `expr !== undefined`) so compiled
25
+ // output stays robust if the emitted call shape changes: a slotId the compiler
26
+ // recorded in `manifest.securityExpressions` is always an expression unit.
27
+ function security(slotId, opts, expr) {
14
28
  const ctx = getCtx("request.security");
15
- return makeSecurityBar(ctx, slotId, opts.interval);
29
+ const symbol = resolveSymbol(ctx, opts.symbol);
30
+ const feed = feedKey(symbol, opts.interval);
31
+ const runner = ctx.securityExprRunners?.get(slotId);
32
+ if (runner === undefined) {
33
+ return makeSecurityBar(ctx, slotId, symbol, opts.interval);
34
+ }
35
+ if (expr !== undefined) {
36
+ const secondary = ctx.secondaryStreams.get(feed);
37
+ if (secondary !== undefined)
38
+ captureAndCatchUp(runner, expr, secondary);
39
+ }
40
+ // `resolveSymbol` collapses an omitted / chart-symbol request to `undefined`,
41
+ // so a defined `symbol` is always a DIFFERENT symbol (the `multiSymbol` gate).
42
+ return makeSecurityExprSeries(ctx, runner, feed, symbol !== undefined);
16
43
  }
17
44
  function lowerTf(slotId, opts) {
18
45
  const ctx = getCtx("request.lowerTf");
@@ -1 +1 @@
1
- {"version":3,"file":"requestNamespace.js","sourceRoot":"","sources":["../../src/request/requestNamespace.ts"],"names":[],"mappings":"AAAA,+DAA+D;AAC/D,+DAA+D;AAW/D,OAAO,EAAE,sBAAsB,EAAuB,MAAM,sBAAsB,CAAC;AACnF,OAAO,EAAE,iBAAiB,EAAE,MAAM,cAAc,CAAC;AACjD,OAAO,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AAEhD,SAAS,MAAM,CAAC,IAAY;IACxB,MAAM,GAAG,GAAG,sBAAsB,CAAC,OAAO,CAAC;IAC3C,IAAI,GAAG,KAAK,IAAI,EAAE,CAAC;QACf,MAAM,IAAI,KAAK,CAAC,GAAG,IAAI,uCAAuC,CAAC,CAAC;IACpE,CAAC;IACD,OAAO,GAAG,CAAC;AACf,CAAC;AAED,SAAS,QAAQ,CAAC,MAAc,EAAE,IAAyB;IACvD,MAAM,GAAG,GAAG,MAAM,CAAC,kBAAkB,CAAC,CAAC;IACvC,OAAO,eAAe,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,CAAC,QAAQ,CAAC,CAAC;AACvD,CAAC;AAED,SAAS,OAAO,CAAC,MAAc,EAAE,IAAwB;IACrD,MAAM,GAAG,GAAG,MAAM,CAAC,iBAAiB,CAAC,CAAC;IACtC,OAAO,iBAAiB,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,CAAC,QAAQ,CAAC,CAAC;AACzD,CAAC;AAED;;;;;;;;;;;;;GAaG;AACH,MAAM,UAAU,qBAAqB;IACjC,MAAM,EAAE,GAAG,MAAM,CAAC,MAAM,CAAC,EAAE,QAAQ,EAAE,OAAO,EAAE,CAAC,CAAC;IAChD,OAAO,EAAiC,CAAC;AAC7C,CAAC","sourcesContent":["// Copyright (c) 2026 Invinite. Licensed under the MIT License.\n// See the LICENSE file in the repo root for full license text.\n\nimport type {\n Bar,\n RequestLowerTfOpts,\n RequestNamespace,\n RequestSecurityOpts,\n SecurityBar,\n Series,\n} from \"@invinite-org/chartlang-core\";\n\nimport { ACTIVE_RUNTIME_CONTEXT, type RuntimeContext } from \"../runtimeContext.js\";\nimport { makeLowerTfSeries } from \"./lowerTf.js\";\nimport { makeSecurityBar } from \"./security.js\";\n\nfunction getCtx(name: string): RuntimeContext {\n const ctx = ACTIVE_RUNTIME_CONTEXT.current;\n if (ctx === null) {\n throw new Error(`${name} called outside an active script step`);\n }\n return ctx;\n}\n\nfunction security(slotId: string, opts: RequestSecurityOpts): SecurityBar {\n const ctx = getCtx(\"request.security\");\n return makeSecurityBar(ctx, slotId, opts.interval);\n}\n\nfunction lowerTf(slotId: string, opts: RequestLowerTfOpts): Series<ReadonlyArray<Bar>> {\n const ctx = getCtx(\"request.lowerTf\");\n return makeLowerTfSeries(ctx, slotId, opts.interval);\n}\n\n/**\n * Build the runtime `request` namespace installed on `ComputeContext`.\n *\n * The implementation accepts the compiler-injected `slotId` as its first\n * parameter even though the public core type is script-facing\n * `request.security(opts)`. This mirrors the existing slot-aware `state.*`\n * runtime namespace.\n *\n * @since 0.4\n * @stable\n * @example\n * const ns = buildRequestNamespace();\n * void ns.security;\n */\nexport function buildRequestNamespace(): RequestNamespace {\n const ns = Object.freeze({ security, lowerTf });\n return ns as unknown as RequestNamespace;\n}\n"]}
1
+ {"version":3,"file":"requestNamespace.js","sourceRoot":"","sources":["../../src/request/requestNamespace.ts"],"names":[],"mappings":"AAAA,+DAA+D;AAC/D,+DAA+D;AAW/D,OAAO,EAAE,OAAO,EAAE,MAAM,8BAA8B,CAAC;AAEvD,OAAO,EAAE,sBAAsB,EAAuB,MAAM,sBAAsB,CAAC;AACnF,OAAO,EAAE,iBAAiB,EAAE,MAAM,cAAc,CAAC;AACjD,OAAO,EAAE,eAAe,EAAE,sBAAsB,EAAE,MAAM,eAAe,CAAC;AACxE,OAAO,EAAE,iBAAiB,EAAE,MAAM,yBAAyB,CAAC;AAE5D,SAAS,MAAM,CAAC,IAAY;IACxB,MAAM,GAAG,GAAG,sBAAsB,CAAC,OAAO,CAAC;IAC3C,IAAI,GAAG,KAAK,IAAI,EAAE,CAAC;QACf,MAAM,IAAI,KAAK,CAAC,GAAG,IAAI,uCAAuC,CAAC,CAAC;IACpE,CAAC;IACD,OAAO,GAAG,CAAC;AACf,CAAC;AAED,+EAA+E;AAC/E,8EAA8E;AAC9E,2EAA2E;AAC3E,8EAA8E;AAC9E,8EAA8E;AAC9E,gCAAgC;AAChC,SAAS,aAAa,CAAC,GAAmB,EAAE,MAA0B;IAClE,OAAO,MAAM,KAAK,SAAS,IAAI,MAAM,KAAK,GAAG,CAAC,WAAW,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,MAAM,CAAC;AACnF,CAAC;AAED,0EAA0E;AAC1E,+EAA+E;AAC/E,2EAA2E;AAC3E,SAAS,QAAQ,CACb,MAAc,EACd,IAAyB,EACzB,IAAmB;IAEnB,MAAM,GAAG,GAAG,MAAM,CAAC,kBAAkB,CAAC,CAAC;IACvC,MAAM,MAAM,GAAG,aAAa,CAAC,GAAG,EAAE,IAAI,CAAC,MAAM,CAAC,CAAC;IAC/C,MAAM,IAAI,GAAG,OAAO,CAAC,MAAM,EAAE,IAAI,CAAC,QAAQ,CAAC,CAAC;IAC5C,MAAM,MAAM,GAAG,GAAG,CAAC,mBAAmB,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC;IACpD,IAAI,MAAM,KAAK,SAAS,EAAE,CAAC;QACvB,OAAO,eAAe,CAAC,GAAG,EAAE,MAAM,EAAE,MAAM,EAAE,IAAI,CAAC,QAAQ,CAAC,CAAC;IAC/D,CAAC;IACD,IAAI,IAAI,KAAK,SAAS,EAAE,CAAC;QACrB,MAAM,SAAS,GAAG,GAAG,CAAC,gBAAgB,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;QACjD,IAAI,SAAS,KAAK,SAAS;YAAE,iBAAiB,CAAC,MAAM,EAAE,IAAI,EAAE,SAAS,CAAC,CAAC;IAC5E,CAAC;IACD,8EAA8E;IAC9E,+EAA+E;IAC/E,OAAO,sBAAsB,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,KAAK,SAAS,CAAC,CAAC;AAC3E,CAAC;AAED,SAAS,OAAO,CAAC,MAAc,EAAE,IAAwB;IACrD,MAAM,GAAG,GAAG,MAAM,CAAC,iBAAiB,CAAC,CAAC;IACtC,OAAO,iBAAiB,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,CAAC,QAAQ,CAAC,CAAC;AACzD,CAAC;AAED;;;;;;;;;;;;;GAaG;AACH,MAAM,UAAU,qBAAqB;IACjC,MAAM,EAAE,GAAG,MAAM,CAAC,MAAM,CAAC,EAAE,QAAQ,EAAE,OAAO,EAAE,CAAC,CAAC;IAChD,OAAO,EAAiC,CAAC;AAC7C,CAAC","sourcesContent":["// Copyright (c) 2026 Invinite. Licensed under the MIT License.\n// See the LICENSE file in the repo root for full license text.\n\nimport type {\n Bar,\n RequestLowerTfOpts,\n RequestNamespace,\n RequestSecurityOpts,\n SecurityBar,\n SecurityExpr,\n Series,\n} from \"@invinite-org/chartlang-core\";\nimport { feedKey } from \"@invinite-org/chartlang-core\";\n\nimport { ACTIVE_RUNTIME_CONTEXT, type RuntimeContext } from \"../runtimeContext.js\";\nimport { makeLowerTfSeries } from \"./lowerTf.js\";\nimport { makeSecurityBar, makeSecurityExprSeries } from \"./security.js\";\nimport { captureAndCatchUp } from \"./securityExprRunner.js\";\n\nfunction getCtx(name: string): RuntimeContext {\n const ctx = ACTIVE_RUNTIME_CONTEXT.current;\n if (ctx === null) {\n throw new Error(`${name} called outside an active script step`);\n }\n return ctx;\n}\n\n// Resolve a requested symbol to the value the secondary stream is keyed under.\n// An omitted symbol — or the chart's own ticker passed explicitly — collapses\n// to `undefined` so `feedKey` produces the bare interval, hitting the same\n// stream as the omitted-symbol form (no duplicate) and staying byte-identical\n// to the pre-multi-symbol baseline. Only a *different* symbol survives as the\n// `\"<symbol>@<interval>\"` feed.\nfunction resolveSymbol(ctx: RuntimeContext, symbol: string | undefined): string | undefined {\n return symbol === undefined || symbol === ctx.chartSymbol ? undefined : symbol;\n}\n\n// Dispatch off the runner registry (not `expr !== undefined`) so compiled\n// output stays robust if the emitted call shape changes: a slotId the compiler\n// recorded in `manifest.securityExpressions` is always an expression unit.\nfunction security(\n slotId: string,\n opts: RequestSecurityOpts,\n expr?: SecurityExpr,\n): SecurityBar | Series<number> {\n const ctx = getCtx(\"request.security\");\n const symbol = resolveSymbol(ctx, opts.symbol);\n const feed = feedKey(symbol, opts.interval);\n const runner = ctx.securityExprRunners?.get(slotId);\n if (runner === undefined) {\n return makeSecurityBar(ctx, slotId, symbol, opts.interval);\n }\n if (expr !== undefined) {\n const secondary = ctx.secondaryStreams.get(feed);\n if (secondary !== undefined) captureAndCatchUp(runner, expr, secondary);\n }\n // `resolveSymbol` collapses an omitted / chart-symbol request to `undefined`,\n // so a defined `symbol` is always a DIFFERENT symbol (the `multiSymbol` gate).\n return makeSecurityExprSeries(ctx, runner, feed, symbol !== undefined);\n}\n\nfunction lowerTf(slotId: string, opts: RequestLowerTfOpts): Series<ReadonlyArray<Bar>> {\n const ctx = getCtx(\"request.lowerTf\");\n return makeLowerTfSeries(ctx, slotId, opts.interval);\n}\n\n/**\n * Build the runtime `request` namespace installed on `ComputeContext`.\n *\n * The implementation accepts the compiler-injected `slotId` as its first\n * parameter even though the public core type is script-facing\n * `request.security(opts)`. This mirrors the existing slot-aware `state.*`\n * runtime namespace.\n *\n * @since 0.4\n * @stable\n * @example\n * const ns = buildRequestNamespace();\n * void ns.security;\n */\nexport function buildRequestNamespace(): RequestNamespace {\n const ns = Object.freeze({ security, lowerTf });\n return ns as unknown as RequestNamespace;\n}\n"]}
@@ -1,5 +1,6 @@
1
- import type { SecurityBar } from "@invinite-org/chartlang-core";
1
+ import type { SecurityBar, Series } from "@invinite-org/chartlang-core";
2
2
  import type { RuntimeContext } from "../runtimeContext.js";
3
+ import { type SecurityExprRunner } from "./securityExprRunner.js";
3
4
  /**
4
5
  * Build the all-NaN `SecurityBar` fallback for unsupported MTF paths.
5
6
  *
@@ -12,14 +13,49 @@ import type { RuntimeContext } from "../runtimeContext.js";
12
13
  */
13
14
  export declare function makeNanSecurityBar(): SecurityBar;
14
15
  /**
15
- * Return the runtime `request.security` bar for a callsite and interval.
16
+ * Return the runtime `request.security` bar for a callsite and `(symbol,
17
+ * interval)` feed. `symbol` is already chart-symbol resolved + collapsed by the
18
+ * caller (`undefined` ⇒ the chart's own symbol), so the composite
19
+ * {@link feedKey} collapses to the bare interval for the chart-symbol path —
20
+ * keeping the cache key, secondary-stream lookup, and diagnostics
21
+ * byte-identical to the pre-multi-symbol baseline.
22
+ *
23
+ * A non-`undefined` `symbol` is therefore always a DIFFERENT symbol: the gate
24
+ * order is symbol (`multiSymbol`) → timeframe (`multiTimeframe`) →
25
+ * `unsupported-interval` → `unknown-secondary-stream`, so a request that is
26
+ * both a different symbol AND a different interval against `multiSymbol: false`
27
+ * trips `multi-symbol-not-supported` first (one diagnostic, not both).
16
28
  *
17
29
  * @since 0.5
18
30
  * @stable
19
31
  * @example
20
- * // const bar = makeSecurityBar(ctx, "slot#0", "1D");
32
+ * // const bar = makeSecurityBar(ctx, "slot#0", undefined, "1D");
21
33
  * const requested = "1D";
22
34
  * void requested;
23
35
  */
24
- export declare function makeSecurityBar(ctx: RuntimeContext, slotId: string, interval: string): SecurityBar;
36
+ export declare function makeSecurityBar(ctx: RuntimeContext, slotId: string, symbol: string | undefined, interval: string): SecurityBar;
37
+ /**
38
+ * Return the main-aligned output series for an HTF expression callsite. The
39
+ * runner's `output` buffer holds one sampled value per HTF bar; this aligns it
40
+ * no-lookahead to the main timeline against the real secondary stream's
41
+ * timestamps (so `output[i]` pairs with secondary ascending bar `i`). Reuses
42
+ * the OHLCV alignment kernel via {@link getOrAlign}. Capability / interval /
43
+ * stream fallbacks return an all-NaN series and push a deduped diagnostic,
44
+ * matching {@link makeSecurityBar}. The returned Proxy identity is cached per
45
+ * `slotId|feedKey` for the bar. `feed` is the composite key the caller built
46
+ * from the resolved `(symbol, interval)`; `runner.interval` is the bare
47
+ * interval used for the capability check and diagnostic text.
48
+ *
49
+ * `isDifferentSymbol` (`true` when the resolved symbol differs from the chart
50
+ * symbol) gates the all-NaN `multi-symbol-not-supported` fallback BEFORE the
51
+ * timeframe gate, mirroring {@link makeSecurityBar}'s order exactly.
52
+ *
53
+ * @since 0.7
54
+ * @stable
55
+ * @example
56
+ * // const trend = makeSecurityExprSeries(ctx, runner, "1W", false);
57
+ * const requested = "1W";
58
+ * void requested;
59
+ */
60
+ export declare function makeSecurityExprSeries(ctx: RuntimeContext, runner: SecurityExprRunner, feed: string, isDifferentSymbol: boolean): Series<number>;
25
61
  //# sourceMappingURL=security.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"security.d.ts","sourceRoot":"","sources":["../../src/request/security.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,WAAW,EAAU,MAAM,8BAA8B,CAAC;AAExE,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AAmC3D;;;;;;;;;GASG;AACH,wBAAgB,kBAAkB,IAAI,WAAW,CAiBhD;AA4HD;;;;;;;;;GASG;AACH,wBAAgB,eAAe,CAC3B,GAAG,EAAE,cAAc,EACnB,MAAM,EAAE,MAAM,EACd,QAAQ,EAAE,MAAM,GACjB,WAAW,CA2Cb"}
1
+ {"version":3,"file":"security.d.ts","sourceRoot":"","sources":["../../src/request/security.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,EAAE,MAAM,8BAA8B,CAAC;AAGxE,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AAI3D,OAAO,EAAE,KAAK,kBAAkB,EAAmB,MAAM,yBAAyB,CAAC;AAgCnF;;;;;;;;;GASG;AACH,wBAAgB,kBAAkB,IAAI,WAAW,CAiBhD;AAmID;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,wBAAgB,eAAe,CAC3B,GAAG,EAAE,cAAc,EACnB,MAAM,EAAE,MAAM,EACd,MAAM,EAAE,MAAM,GAAG,SAAS,EAC1B,QAAQ,EAAE,MAAM,GACjB,WAAW,CAyDb;AAgDD;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,wBAAgB,sBAAsB,CAClC,GAAG,EAAE,cAAc,EACnB,MAAM,EAAE,kBAAkB,EAC1B,IAAI,EAAE,MAAM,EACZ,iBAAiB,EAAE,OAAO,GAC3B,MAAM,CAAC,MAAM,CAAC,CAkChB"}
@@ -1,8 +1,10 @@
1
1
  // Copyright (c) 2026 Invinite. Licensed under the MIT License.
2
2
  // See the LICENSE file in the repo root for full license text.
3
+ import { feedKey } from "@invinite-org/chartlang-core";
3
4
  import { getOrAlign } from "./alignHtfSeriesCache.js";
4
5
  import { pushOnce } from "./pushOnce.js";
5
- import { ascendingBarsFor } from "./streamBars.js";
6
+ import { ascendingValues } from "./securityExprRunner.js";
7
+ import { ascendingBarsFor, makeConstantStringSeries } from "./streamBars.js";
6
8
  const NUMERIC_SOURCE_KEYS = Object.freeze([
7
9
  "time",
8
10
  "open",
@@ -54,11 +56,11 @@ function seriesAscending(stream, sourceKey) {
54
56
  }
55
57
  return values;
56
58
  }
57
- function alignmentKey(slotId, interval, sourceKey) {
58
- return `${slotId}|${interval}|${sourceKey}`;
59
+ function alignmentKey(slotId, feed, sourceKey) {
60
+ return `${slotId}|${feed}|${sourceKey}`;
59
61
  }
60
- function alignedSeries(ctx, slotId, interval, sourceKey, secondary) {
61
- const key = alignmentKey(slotId, interval, sourceKey);
62
+ function alignedSeries(ctx, slotId, feed, sourceKey, secondary) {
63
+ const key = alignmentKey(slotId, feed, sourceKey);
62
64
  const existing = ctx.requestSecurityAlignments.get(key);
63
65
  if (existing !== undefined)
64
66
  return existing;
@@ -68,10 +70,17 @@ function alignedSeries(ctx, slotId, interval, sourceKey, secondary) {
68
70
  ctx.requestSecurityAlignments.set(key, aligned);
69
71
  return aligned;
70
72
  }
71
- function makeAlignedNumberSeries(ctx, slotId, interval, sourceKey, secondary) {
73
+ /**
74
+ * Wrap a producer of the latest main-aligned array in the head-relative
75
+ * `Series<number>` Proxy shape. `current` / `[n]` re-run `produce` (cheap —
76
+ * `getOrAlign` memoises per bar) and read from the tail; `length` is the main
77
+ * stream's bar count. Shared by the OHLCV `SecurityBar` fields and the
78
+ * expression-output series so both walk the identical no-lookahead alignment.
79
+ */
80
+ function makeAlignedSeriesProxy(ctx, produce) {
72
81
  const target = {
73
82
  get current() {
74
- const aligned = alignedSeries(ctx, slotId, interval, sourceKey, secondary);
83
+ const aligned = produce();
75
84
  const value = aligned[aligned.length - 1];
76
85
  return value === undefined ? Number.NaN : value;
77
86
  },
@@ -84,7 +93,7 @@ function makeAlignedNumberSeries(ctx, slotId, interval, sourceKey, secondary) {
84
93
  if (typeof prop === "string") {
85
94
  const n = Number(prop);
86
95
  if (Number.isInteger(n) && n >= 0) {
87
- const aligned = alignedSeries(ctx, slotId, interval, sourceKey, secondary);
96
+ const aligned = produce();
88
97
  const value = aligned[aligned.length - 1 - n];
89
98
  return value === undefined ? Number.NaN : value;
90
99
  }
@@ -93,30 +102,13 @@ function makeAlignedNumberSeries(ctx, slotId, interval, sourceKey, secondary) {
93
102
  },
94
103
  });
95
104
  }
96
- function makeConstantStringSeries(value) {
97
- const target = {
98
- get current() {
99
- return value;
100
- },
101
- get length() {
102
- return 0;
103
- },
104
- };
105
- return new Proxy(Object.freeze(target), {
106
- get(obj, prop, receiver) {
107
- if (typeof prop === "string") {
108
- const n = Number(prop);
109
- if (Number.isInteger(n) && n >= 0)
110
- return value;
111
- }
112
- return Reflect.get(obj, prop, receiver);
113
- },
114
- });
105
+ function makeAlignedNumberSeries(ctx, slotId, feed, sourceKey, secondary) {
106
+ return makeAlignedSeriesProxy(ctx, () => alignedSeries(ctx, slotId, feed, sourceKey, secondary));
115
107
  }
116
- function makeLiveSecurityBar(ctx, slotId, interval, secondary) {
108
+ function makeLiveSecurityBar(ctx, slotId, feed, interval, secondary) {
117
109
  const numeric = new Map();
118
110
  for (const key of NUMERIC_SOURCE_KEYS) {
119
- numeric.set(key, makeAlignedNumberSeries(ctx, slotId, interval, key, secondary));
111
+ numeric.set(key, makeAlignedNumberSeries(ctx, slotId, feed, key, secondary));
120
112
  }
121
113
  return Object.freeze({
122
114
  time: numeric.get("time") ?? makeSeries(Number.NaN),
@@ -133,40 +125,122 @@ function makeLiveSecurityBar(ctx, slotId, interval, secondary) {
133
125
  interval: makeConstantStringSeries(interval),
134
126
  });
135
127
  }
136
- function fallbackNaN(ctx, cacheKey, slotId, interval, code, message) {
137
- pushOnce(ctx, code, slotId, interval, "security", message);
128
+ // The adapter does not advertise `multiSymbol`, so a `request.security` for a
129
+ // symbol other than the chart's own degrades to all-NaN — mirroring the
130
+ // `multiTimeframe` fallback message exactly, only naming the symbol gate.
131
+ const MULTI_SYMBOL_MSG = "Adapter declares multiSymbol: false; request.security for a different symbol returns NaN";
132
+ function fallbackNaN(ctx, cacheKey, slotId, feed, code, message) {
133
+ pushOnce(ctx, code, slotId, feed, "security", message);
138
134
  const bar = makeNanSecurityBar();
139
135
  ctx.requestSecurityBars.set(cacheKey, bar);
140
136
  return bar;
141
137
  }
142
138
  /**
143
- * Return the runtime `request.security` bar for a callsite and interval.
139
+ * Return the runtime `request.security` bar for a callsite and `(symbol,
140
+ * interval)` feed. `symbol` is already chart-symbol resolved + collapsed by the
141
+ * caller (`undefined` ⇒ the chart's own symbol), so the composite
142
+ * {@link feedKey} collapses to the bare interval for the chart-symbol path —
143
+ * keeping the cache key, secondary-stream lookup, and diagnostics
144
+ * byte-identical to the pre-multi-symbol baseline.
145
+ *
146
+ * A non-`undefined` `symbol` is therefore always a DIFFERENT symbol: the gate
147
+ * order is symbol (`multiSymbol`) → timeframe (`multiTimeframe`) →
148
+ * `unsupported-interval` → `unknown-secondary-stream`, so a request that is
149
+ * both a different symbol AND a different interval against `multiSymbol: false`
150
+ * trips `multi-symbol-not-supported` first (one diagnostic, not both).
144
151
  *
145
152
  * @since 0.5
146
153
  * @stable
147
154
  * @example
148
- * // const bar = makeSecurityBar(ctx, "slot#0", "1D");
155
+ * // const bar = makeSecurityBar(ctx, "slot#0", undefined, "1D");
149
156
  * const requested = "1D";
150
157
  * void requested;
151
158
  */
152
- export function makeSecurityBar(ctx, slotId, interval) {
153
- const cacheKey = `${slotId}|${interval}`;
159
+ export function makeSecurityBar(ctx, slotId, symbol, interval) {
160
+ const feed = feedKey(symbol, interval);
161
+ const cacheKey = `${slotId}|${feed}`;
154
162
  const existing = ctx.requestSecurityBars.get(cacheKey);
155
163
  if (existing !== undefined)
156
164
  return existing;
165
+ // Symbol gate precedes the timeframe gate: a different symbol is a strictly
166
+ // larger ask than a higher timeframe of the chart's own symbol.
167
+ if (symbol !== undefined && !ctx.capabilities.multiSymbol) {
168
+ return fallbackNaN(ctx, cacheKey, slotId, feed, "multi-symbol-not-supported", MULTI_SYMBOL_MSG);
169
+ }
157
170
  if (!ctx.capabilities.multiTimeframe) {
158
- return fallbackNaN(ctx, cacheKey, slotId, interval, "multi-timeframe-not-supported", "Adapter declares multiTimeframe: false; request.security returns NaN");
171
+ return fallbackNaN(ctx, cacheKey, slotId, feed, "multi-timeframe-not-supported", "Adapter declares multiTimeframe: false; request.security returns NaN");
159
172
  }
160
173
  const known = ctx.capabilities.intervals.some((descriptor) => descriptor.value === interval);
161
174
  if (!known) {
162
- return fallbackNaN(ctx, cacheKey, slotId, interval, "unsupported-interval", `Requested interval "${interval}" is not in Capabilities.intervals`);
175
+ return fallbackNaN(ctx, cacheKey, slotId, feed, "unsupported-interval", `Requested interval "${interval}" is not in Capabilities.intervals`);
163
176
  }
164
- const secondary = ctx.secondaryStreams.get(interval);
177
+ const secondary = ctx.secondaryStreams.get(feed);
165
178
  if (secondary === undefined) {
166
- return fallbackNaN(ctx, cacheKey, slotId, interval, "unknown-secondary-stream", `Requested interval "${interval}" has no registered secondary stream`);
179
+ return fallbackNaN(ctx, cacheKey, slotId, feed, "unknown-secondary-stream", `Requested interval "${interval}" has no registered secondary stream`);
167
180
  }
168
- const bar = makeLiveSecurityBar(ctx, slotId, interval, secondary);
181
+ const bar = makeLiveSecurityBar(ctx, slotId, feed, interval, secondary);
169
182
  ctx.requestSecurityBars.set(cacheKey, bar);
170
183
  return bar;
171
184
  }
185
+ function makeNanNumberSeries() {
186
+ return makeSeries(Number.NaN);
187
+ }
188
+ function resolveSecondaryOrDiagnose(ctx, slotId, feed, interval) {
189
+ if (!ctx.capabilities.multiTimeframe) {
190
+ pushOnce(ctx, "multi-timeframe-not-supported", slotId, feed, "security", "Adapter declares multiTimeframe: false; request.security returns NaN");
191
+ return undefined;
192
+ }
193
+ if (!ctx.capabilities.intervals.some((descriptor) => descriptor.value === interval)) {
194
+ pushOnce(ctx, "unsupported-interval", slotId, feed, "security", `Requested interval "${interval}" is not in Capabilities.intervals`);
195
+ return undefined;
196
+ }
197
+ const secondary = ctx.secondaryStreams.get(feed);
198
+ if (secondary === undefined) {
199
+ pushOnce(ctx, "unknown-secondary-stream", slotId, feed, "security", `Requested interval "${interval}" has no registered secondary stream`);
200
+ }
201
+ return secondary;
202
+ }
203
+ /**
204
+ * Return the main-aligned output series for an HTF expression callsite. The
205
+ * runner's `output` buffer holds one sampled value per HTF bar; this aligns it
206
+ * no-lookahead to the main timeline against the real secondary stream's
207
+ * timestamps (so `output[i]` pairs with secondary ascending bar `i`). Reuses
208
+ * the OHLCV alignment kernel via {@link getOrAlign}. Capability / interval /
209
+ * stream fallbacks return an all-NaN series and push a deduped diagnostic,
210
+ * matching {@link makeSecurityBar}. The returned Proxy identity is cached per
211
+ * `slotId|feedKey` for the bar. `feed` is the composite key the caller built
212
+ * from the resolved `(symbol, interval)`; `runner.interval` is the bare
213
+ * interval used for the capability check and diagnostic text.
214
+ *
215
+ * `isDifferentSymbol` (`true` when the resolved symbol differs from the chart
216
+ * symbol) gates the all-NaN `multi-symbol-not-supported` fallback BEFORE the
217
+ * timeframe gate, mirroring {@link makeSecurityBar}'s order exactly.
218
+ *
219
+ * @since 0.7
220
+ * @stable
221
+ * @example
222
+ * // const trend = makeSecurityExprSeries(ctx, runner, "1W", false);
223
+ * const requested = "1W";
224
+ * void requested;
225
+ */
226
+ export function makeSecurityExprSeries(ctx, runner, feed, isDifferentSymbol) {
227
+ const cacheKey = `${runner.slotId}|${feed}`;
228
+ const cache = ctx.requestSecurityExprSeries;
229
+ const existing = cache?.get(cacheKey);
230
+ if (existing !== undefined)
231
+ return existing;
232
+ // Symbol gate precedes the timeframe gate, matching `makeSecurityBar`.
233
+ if (isDifferentSymbol && !ctx.capabilities.multiSymbol) {
234
+ pushOnce(ctx, "multi-symbol-not-supported", runner.slotId, feed, "security", MULTI_SYMBOL_MSG);
235
+ const nan = makeNanNumberSeries();
236
+ cache?.set(cacheKey, nan);
237
+ return nan;
238
+ }
239
+ const secondary = resolveSecondaryOrDiagnose(ctx, runner.slotId, feed, runner.interval);
240
+ const series = secondary === undefined
241
+ ? makeNanNumberSeries()
242
+ : makeAlignedSeriesProxy(ctx, () => getOrAlign(ascendingBarsFor(ctx, secondary), ascendingValues(runner.output), ascendingBarsFor(ctx, ctx.stream)));
243
+ cache?.set(cacheKey, series);
244
+ return series;
245
+ }
172
246
  //# sourceMappingURL=security.js.map