@invinite-org/chartlang-runtime 1.2.0 → 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 (114) hide show
  1. package/CHANGELOG.md +71 -0
  2. package/dist/buildComputeContext.d.ts.map +1 -1
  3. package/dist/buildComputeContext.js +6 -1
  4. package/dist/buildComputeContext.js.map +1 -1
  5. package/dist/createScriptRunner.d.ts.map +1 -1
  6. package/dist/createScriptRunner.js +37 -7
  7. package/dist/createScriptRunner.js.map +1 -1
  8. package/dist/dep/DepRunner.d.ts +7 -0
  9. package/dist/dep/DepRunner.d.ts.map +1 -1
  10. package/dist/dep/DepRunner.js +3 -0
  11. package/dist/dep/DepRunner.js.map +1 -1
  12. package/dist/emit/barcolor.d.ts +44 -0
  13. package/dist/emit/barcolor.d.ts.map +1 -0
  14. package/dist/emit/barcolor.js +40 -0
  15. package/dist/emit/barcolor.js.map +1 -0
  16. package/dist/emit/bgcolor.d.ts +44 -0
  17. package/dist/emit/bgcolor.d.ts.map +1 -0
  18. package/dist/emit/bgcolor.js +45 -0
  19. package/dist/emit/bgcolor.js.map +1 -0
  20. package/dist/emit/index.d.ts +2 -0
  21. package/dist/emit/index.d.ts.map +1 -1
  22. package/dist/emit/index.js +2 -0
  23. package/dist/emit/index.js.map +1 -1
  24. package/dist/emit/plot.d.ts +23 -1
  25. package/dist/emit/plot.d.ts.map +1 -1
  26. package/dist/emit/plot.js +32 -1
  27. package/dist/emit/plot.js.map +1 -1
  28. package/dist/execution/dispose.d.ts.map +1 -1
  29. package/dist/execution/dispose.js +3 -1
  30. package/dist/execution/dispose.js.map +1 -1
  31. package/dist/execution/runComputeStep.d.ts.map +1 -1
  32. package/dist/execution/runComputeStep.js +3 -1
  33. package/dist/execution/runComputeStep.js.map +1 -1
  34. package/dist/inputs/resolveInputs.js +1 -0
  35. package/dist/inputs/resolveInputs.js.map +1 -1
  36. package/dist/persistentStateStore.runtime.d.ts.map +1 -1
  37. package/dist/persistentStateStore.runtime.js +10 -5
  38. package/dist/persistentStateStore.runtime.js.map +1 -1
  39. package/dist/primitives.d.ts +1 -1
  40. package/dist/primitives.d.ts.map +1 -1
  41. package/dist/primitives.js +7 -1
  42. package/dist/primitives.js.map +1 -1
  43. package/dist/request/lowerTf.d.ts.map +1 -1
  44. package/dist/request/lowerTf.js +6 -0
  45. package/dist/request/lowerTf.js.map +1 -1
  46. package/dist/request/requestNamespace.d.ts.map +1 -1
  47. package/dist/request/requestNamespace.js +17 -3
  48. package/dist/request/requestNamespace.js.map +1 -1
  49. package/dist/request/security.d.ts +23 -6
  50. package/dist/request/security.d.ts.map +1 -1
  51. package/dist/request/security.js +64 -29
  52. package/dist/request/security.js.map +1 -1
  53. package/dist/request/securityExprRunner.d.ts +12 -8
  54. package/dist/request/securityExprRunner.d.ts.map +1 -1
  55. package/dist/request/securityExprRunner.js +32 -14
  56. package/dist/request/securityExprRunner.js.map +1 -1
  57. package/dist/ringBuffer.d.ts +19 -0
  58. package/dist/ringBuffer.d.ts.map +1 -1
  59. package/dist/ringBuffer.js +23 -0
  60. package/dist/ringBuffer.js.map +1 -1
  61. package/dist/runtimeContext.d.ts +49 -12
  62. package/dist/runtimeContext.d.ts.map +1 -1
  63. package/dist/runtimeContext.js.map +1 -1
  64. package/dist/state/arrayPersistence.d.ts +48 -0
  65. package/dist/state/arrayPersistence.d.ts.map +1 -0
  66. package/dist/state/arrayPersistence.js +88 -0
  67. package/dist/state/arrayPersistence.js.map +1 -0
  68. package/dist/state/arrayStateSlot.d.ts +78 -0
  69. package/dist/state/arrayStateSlot.d.ts.map +1 -0
  70. package/dist/state/arrayStateSlot.js +116 -0
  71. package/dist/state/arrayStateSlot.js.map +1 -0
  72. package/dist/state/index.d.ts +3 -1
  73. package/dist/state/index.d.ts.map +1 -1
  74. package/dist/state/index.js +3 -1
  75. package/dist/state/index.js.map +1 -1
  76. package/dist/state/lifecycle.d.ts +28 -0
  77. package/dist/state/lifecycle.d.ts.map +1 -1
  78. package/dist/state/lifecycle.js +36 -0
  79. package/dist/state/lifecycle.js.map +1 -1
  80. package/dist/state/stateNamespace.d.ts.map +1 -1
  81. package/dist/state/stateNamespace.js +27 -0
  82. package/dist/state/stateNamespace.js.map +1 -1
  83. package/dist/ta/sessionVolumeProfile.d.ts.map +1 -1
  84. package/dist/ta/sessionVolumeProfile.js +1 -17
  85. package/dist/ta/sessionVolumeProfile.js.map +1 -1
  86. package/dist/time-accessors/civil.d.ts +73 -0
  87. package/dist/time-accessors/civil.d.ts.map +1 -0
  88. package/dist/time-accessors/civil.js +105 -0
  89. package/dist/time-accessors/civil.js.map +1 -0
  90. package/dist/time-accessors/index.d.ts +8 -0
  91. package/dist/time-accessors/index.d.ts.map +1 -0
  92. package/dist/time-accessors/index.js +9 -0
  93. package/dist/time-accessors/index.js.map +1 -0
  94. package/dist/time-accessors/sessionAccessors.d.ts +50 -0
  95. package/dist/time-accessors/sessionAccessors.d.ts.map +1 -0
  96. package/dist/time-accessors/sessionAccessors.js +79 -0
  97. package/dist/time-accessors/sessionAccessors.js.map +1 -0
  98. package/dist/time-accessors/sessionWindow.d.ts +17 -0
  99. package/dist/time-accessors/sessionWindow.d.ts.map +1 -0
  100. package/dist/time-accessors/sessionWindow.js +41 -0
  101. package/dist/time-accessors/sessionWindow.js.map +1 -0
  102. package/dist/time-accessors/timeAccessors.d.ts +54 -0
  103. package/dist/time-accessors/timeAccessors.d.ts.map +1 -0
  104. package/dist/time-accessors/timeAccessors.js +132 -0
  105. package/dist/time-accessors/timeAccessors.js.map +1 -0
  106. package/dist/time-accessors/tzDiagnostic.d.ts +17 -0
  107. package/dist/time-accessors/tzDiagnostic.d.ts.map +1 -0
  108. package/dist/time-accessors/tzDiagnostic.js +34 -0
  109. package/dist/time-accessors/tzDiagnostic.js.map +1 -0
  110. package/dist/time-accessors/tzOffset.d.ts +31 -0
  111. package/dist/time-accessors/tzOffset.d.ts.map +1 -0
  112. package/dist/time-accessors/tzOffset.js +67 -0
  113. package/dist/time-accessors/tzOffset.js.map +1 -0
  114. package/package.json +3 -3
@@ -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 {\n isSeriesSlotSnapshotKey,\n restoreSeriesSlots,\n restoreStateSlots,\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 ...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 } 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 both `ta:` (restored onto the stream)\n// and `:series` (restored into `ctx.seriesSlots`) so the scalar slot store\n// receives neither.\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 (!isTaSlotSnapshotKey(slotKey) && !isSeriesSlotSnapshotKey(slotKey)) {\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}\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"]}
1
+ {"version":3,"file":"persistentStateStore.runtime.js","sourceRoot":"","sources":["../src/persistentStateStore.runtime.ts"],"names":[],"mappings":"AAAA,+DAA+D;AAC/D,+DAA+D;AAU/D,OAAO,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAC;AACjD,OAAO,EAAE,gBAAgB,EAAE,MAAM,oCAAoC,CAAC;AAEtE,OAAO,EACH,sBAAsB,EACtB,uBAAuB,EACvB,iBAAiB,EACjB,kBAAkB,EAClB,iBAAiB,EACjB,mBAAmB,EACnB,oBAAoB,EACpB,mBAAmB,GACtB,MAAM,kBAAkB,CAAC;AAC1B,OAAO,EAAE,mBAAmB,EAAE,cAAc,EAAE,gBAAgB,EAAE,MAAM,qBAAqB,CAAC;AAE5F;;;;;;;;GAQG;AACH,MAAM,CAAC,MAAM,uBAAuB,GAAG,MAAM,CAAC;AAE9C,SAAS,cAAc,CAAC,QAAuB;IAC3C,MAAM,OAAO,GAAG,MAAM,CAAC,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC;IACjD,MAAM,KAAK,GAAG,OAAO,CAAC,CAAC,CAAC,CAAC;IACzB,OAAO,KAAK,KAAK,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;AACjD,CAAC;AAED,SAAS,cAAc,CAAC,KAAkB;IACtC,MAAM,IAAI,GAAG,KAAK,CAAC,UAAU,CAAC,iBAAiB,EAAE,CAAC;IAClD,MAAM,OAAO,GAAmC;QAC5C,CAAC,IAAI,CAAC,QAAQ,KAAK,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,EAAE,IAAI;KACxD,CAAC;IACF,KAAK,MAAM,CAAC,GAAG,EAAE,MAAM,CAAC,IAAI,KAAK,CAAC,cAAc,CAAC,gBAAgB,EAAE,CAAC;QAChE,OAAO,CAAC,GAAG,CAAC,GAAG,MAAM,CAAC,iBAAiB,EAAE,CAAC;IAC9C,CAAC;IACD,OAAO,MAAM,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;AAClC,CAAC;AAED,SAAS,mBAAmB,CAAC,KAAkB;IAC3C,OAAO,MAAM,CAAC,MAAM,CAAC;QACjB,GAAG,mBAAmB,CAAC,KAAK,CAAC,cAAc,CAAC;QAC5C,GAAG,oBAAoB,CAAC,KAAK,CAAC,cAAc,CAAC;QAC7C,GAAG,mBAAmB,CAAC,KAAK,CAAC,cAAc,CAAC;QAC5C,GAAG,gBAAgB,CAAC,KAAK,CAAC,UAAU,CAAC;KACX,CAAC,CAAC;AACpC,CAAC;AAED,SAAS,aAAa,CAAC,GAAmB;IACtC,OAAO,MAAM,CAAC,MAAM,CAAC;QACjB,KAAK,EAAE,MAAM,CAAC,MAAM,CAAC;YACjB,GAAG,mBAAmB,CAAC,GAAG,CAAC;YAC3B,GAAG,oBAAoB,CAAC,GAAG,CAAC;YAC5B,GAAG,mBAAmB,CAAC,GAAG,CAAC;SACD,CAAC;KAClC,CAAC,CAAC;AACP,CAAC;AAED,SAAS,eAAe,CAAC,KAAkB;IACvC,IAAI,KAAK,CAAC,cAAc,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,SAAS,CAAC;IACxD,MAAM,GAAG,GAAmC,EAAE,CAAC;IAC/C,KAAK,MAAM,OAAO,IAAI,KAAK,CAAC,cAAc,EAAE,CAAC;QACzC,GAAG,CAAC,OAAO,CAAC,UAAU,CAAC,GAAG,aAAa,CAAC,OAAO,CAAC,KAAK,CAAC,cAAc,CAAC,CAAC;IAC1E,CAAC;IACD,OAAO,MAAM,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;AAC9B,CAAC;AAED,SAAS,mBAAmB,CACxB,KAAkB;IAElB,IAAI,KAAK,CAAC,UAAU,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,SAAS,CAAC;IACpD,MAAM,GAAG,GAAmC,EAAE,CAAC;IAC/C,KAAK,MAAM,GAAG,IAAI,KAAK,CAAC,UAAU,EAAE,CAAC;QACjC,GAAG,CAAC,GAAG,CAAC,OAAO,CAAC,GAAG,aAAa,CAAC,GAAG,CAAC,KAAK,CAAC,cAAc,CAAC,CAAC;IAC/D,CAAC;IACD,OAAO,MAAM,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;AAC9B,CAAC;AAED;;;;;;;;;;;;;;GAcG;AACH,MAAM,UAAU,oBAAoB,CAAC,KAAkB,EAAE,OAAe;IACpE,MAAM,OAAO,GAAG,cAAc,CAAC,KAAK,CAAC,CAAC;IACtC,MAAM,QAAQ,GAAG,eAAe,CAAC,KAAK,CAAC,CAAC;IACxC,MAAM,YAAY,GAAG,mBAAmB,CAAC,KAAK,CAAC,CAAC;IAChD,MAAM,SAAS,GAAkB;QAC7B,WAAW,EAAE,KAAK,CAAC,UAAU,CAAC,GAAG,CAAC,IAAI;QACtC,OAAO;QACP,OAAO;QACP,eAAe,EAAE,CAAC;QAClB,OAAO,EAAE,EAAE,KAAK,EAAE,mBAAmB,CAAC,KAAK,CAAC,EAAE;QAC9C,GAAG,CAAC,QAAQ,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,QAAQ,EAAE,CAAC;QAC/C,GAAG,CAAC,YAAY,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,YAAY,EAAE,CAAC;KAC1D,CAAC;IACF,IAAI,CAAC,gBAAgB,CAAC,SAAS,CAAC;QAAE,OAAO,IAAI,CAAC;IAC9C,OAAO,SAAS,CAAC;AACrB,CAAC;AAED,+EAA+E;AAC/E,8EAA8E;AAC9E,+EAA+E;AAC/E,kCAAkC;AAClC,SAAS,yBAAyB,CAC9B,QAAuB,EACvB,YAAoB;IAEpB,MAAM,MAAM,GAAG,YAAY,KAAK,EAAE,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,QAAQ,CAAC,OAAO,CAAC,YAAY,CAAC,CAAC;IAChF,IAAI,MAAM,KAAK,SAAS;QAAE,OAAO,MAAM,CAAC;IACxC,MAAM,QAAQ,GAAG,cAAc,CAAC,QAAQ,CAAC,CAAC;IAC1C,OAAO,QAAQ,KAAK,IAAI,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,QAAQ,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC;AACtE,CAAC;AAED,uEAAuE;AACvE,2EAA2E;AAC3E,oEAAoE;AACpE,SAAS,gBAAgB,CAAC,KAAwC;IAC9D,MAAM,GAAG,GAA4B,EAAE,CAAC;IACxC,KAAK,MAAM,CAAC,OAAO,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC;QACnD,IACI,CAAC,mBAAmB,CAAC,OAAO,CAAC;YAC7B,CAAC,uBAAuB,CAAC,OAAO,CAAC;YACjC,CAAC,sBAAsB,CAAC,OAAO,CAAC,EAClC,CAAC;YACC,GAAG,CAAC,OAAO,CAAC,GAAG,KAAK,CAAC;QACzB,CAAC;IACL,CAAC;IACD,OAAO,GAAG,CAAC;AACf,CAAC;AAED,0EAA0E;AAC1E,4EAA4E;AAC5E,+CAA+C;AAC/C,SAAS,kBAAkB,CACvB,GAAmB,EACnB,KAAwC,EACxC,QAAgB;IAEhB,iBAAiB,CAAC,GAAG,EAAE,gBAAgB,CAAC,KAAK,CAAC,CAAC,CAAC;IAChD,kBAAkB,CAAC,GAAG,EAAE,KAAK,EAAE,QAAQ,CAAC,CAAC;IACzC,iBAAiB,CAAC,GAAG,EAAE,KAAK,CAAC,CAAC;AAClC,CAAC;AAED,SAAS,oBAAoB,CAAC,KAAkB,EAAE,OAAe;IAC7D,cAAc,CAAC,KAAK,CAAC,SAAS,EAAE;QAC5B,IAAI,EAAE,YAAY;QAClB,QAAQ,EAAE,SAAS;QACnB,IAAI,EAAE,0BAA0B;QAChC,OAAO;QACP,MAAM,EAAE,IAAI;QACZ,GAAG,EAAE,KAAK,CAAC,QAAQ;KACtB,CAAC,CAAC;AACP,CAAC;AAED,SAAS,sBAAsB,CAC3B,KAAkB,EAClB,QAAkD;IAElD,MAAM,MAAM,GAAG,IAAI,GAAG,CAAC,KAAK,CAAC,cAAc,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC,GAAG,CAAC,UAAU,EAAE,GAAG,CAAC,CAAC,CAAC,CAAC;IACjF,KAAK,MAAM,CAAC,UAAU,EAAE,OAAO,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,QAAQ,CAAC,EAAE,CAAC;QAC3D,MAAM,OAAO,GAAG,MAAM,CAAC,GAAG,CAAC,UAAU,CAAC,CAAC;QACvC,IAAI,OAAO,KAAK,SAAS,EAAE,CAAC;YACxB,oBAAoB,CAChB,KAAK,EACL,yDAAyD,UAAU,GAAG,CACzE,CAAC;YACF,SAAS;QACb,CAAC;QACD,kBAAkB,CACd,OAAO,CAAC,KAAK,CAAC,cAAc,EAC5B,OAAO,CAAC,KAAK,EACb,KAAK,CAAC,UAAU,CAAC,KAAK,CAAC,KAAK,CAAC,QAAQ,CACxC,CAAC;IACN,CAAC;AACL,CAAC;AAED,SAAS,yBAAyB,CAC9B,KAAkB,EAClB,YAAsD;IAEtD,MAAM,MAAM,GAAG,IAAI,GAAG,CAAC,KAAK,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC,GAAG,CAAC,OAAO,EAAE,GAAG,CAAC,CAAC,CAAC,CAAC;IAC1E,KAAK,MAAM,CAAC,OAAO,EAAE,OAAO,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,YAAY,CAAC,EAAE,CAAC;QAC5D,MAAM,GAAG,GAAG,MAAM,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;QAChC,IAAI,GAAG,KAAK,SAAS,EAAE,CAAC;YACpB,oBAAoB,CAChB,KAAK,EACL,4DAA4D,OAAO,GAAG,CACzE,CAAC;YACF,SAAS;QACb,CAAC;QACD,kBAAkB,CACd,GAAG,CAAC,KAAK,CAAC,cAAc,EACxB,OAAO,CAAC,KAAK,EACb,KAAK,CAAC,UAAU,CAAC,KAAK,CAAC,KAAK,CAAC,QAAQ,CACxC,CAAC;IACN,CAAC;AACL,CAAC;AAED;;;;;;;;;;;;;;;;;;GAkBG;AACH,MAAM,UAAU,oBAAoB,CAAC,KAAkB,EAAE,QAAuB;IAC5E,MAAM,MAAM,GAAG,yBAAyB,CAAC,QAAQ,EAAE,KAAK,CAAC,UAAU,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;IAClF,IAAI,MAAM,KAAK,SAAS,EAAE,CAAC;QACvB,KAAK,CAAC,UAAU,CAAC,mBAAmB,CAAC,MAAM,CAAC,CAAC;QAC7C,KAAK,CAAC,QAAQ,GAAG,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,QAAQ,EAAE,MAAM,CAAC,MAAM,CAAC,CAAC;IAC7D,CAAC;IACD,KAAK,MAAM,CAAC,YAAY,EAAE,SAAS,CAAC,IAAI,KAAK,CAAC,cAAc,CAAC,gBAAgB,EAAE,CAAC;QAC5E,MAAM,iBAAiB,GAAG,QAAQ,CAAC,OAAO,CAAC,YAAY,CAAC,CAAC;QACzD,IAAI,iBAAiB,KAAK,SAAS,EAAE,CAAC;YAClC,SAAS,CAAC,mBAAmB,CAAC,iBAAiB,CAAC,CAAC;QACrD,CAAC;IACL,CAAC;IAED,MAAM,YAAY,GAAG,cAAc,CAAC,QAAQ,CAAC,CAAC;IAC9C,cAAc,CAAC,KAAK,CAAC,UAAU,EAAE,YAAY,CAAC,CAAC;IAC/C,kBAAkB,CAAC,KAAK,CAAC,cAAc,EAAE,YAAY,EAAE,KAAK,CAAC,UAAU,CAAC,KAAK,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC;IAE9F,IAAI,QAAQ,CAAC,QAAQ,KAAK,SAAS,EAAE,CAAC;QAClC,sBAAsB,CAAC,KAAK,EAAE,QAAQ,CAAC,QAAQ,CAAC,CAAC;IACrD,CAAC;IACD,IAAI,QAAQ,CAAC,YAAY,KAAK,SAAS,EAAE,CAAC;QACtC,yBAAyB,CAAC,KAAK,EAAE,QAAQ,CAAC,YAAY,CAAC,CAAC;IAC5D,CAAC;AACL,CAAC;AAiBD,MAAM,WAAW,GAAwC,MAAM,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC;AAE3E,SAAS,cAAc,CAAC,QAAuB;IAC3C,MAAM,IAAI,GAAG,QAA8B,CAAC;IAC5C,IAAI,IAAI,CAAC,OAAO,KAAK,SAAS;QAAE,OAAO,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC;IAC1D,qFAAqF;IACrF,IAAI,IAAI,CAAC,KAAK,KAAK,SAAS;QAAE,OAAO,WAAW,CAAC;IACjD,OAAO,IAAI,CAAC,KAAK,CAAC;AACtB,CAAC;AAED;;;;;;;;;GASG;AACH,MAAM,CAAC,KAAK,UAAU,iBAAiB,CAAC,KAAkB,EAAE,OAAe;IACvE,MAAM,KAAK,GAAG,KAAK,CAAC,cAAc,CAAC,oBAAoB,CAAC;IACxD,IAAI,KAAK,KAAK,SAAS;QAAE,OAAO,KAAK,CAAC;IACtC,MAAM,QAAQ,GAAG,oBAAoB,CAAC,KAAK,EAAE,OAAO,CAAC,CAAC;IACtD,IAAI,QAAQ,KAAK,IAAI,EAAE,CAAC;QACpB,cAAc,CAAC,KAAK,CAAC,SAAS,EAAE;YAC5B,IAAI,EAAE,YAAY;YAClB,QAAQ,EAAE,SAAS;YACnB,IAAI,EAAE,0BAA0B;YAChC,OAAO,EAAE,8CAA8C;YACvD,MAAM,EAAE,IAAI;YACZ,GAAG,EAAE,KAAK,CAAC,QAAQ;SACtB,CAAC,CAAC;QACH,OAAO,KAAK,CAAC;IACjB,CAAC;IACD,IAAI,CAAC;QACD,MAAM,KAAK,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;QAC3B,KAAK,CAAC,cAAc,CAAC,eAAe,GAAG,OAAO,CAAC;QAC/C,OAAO,IAAI,CAAC;IAChB,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACX,cAAc,CAAC,KAAK,CAAC,SAAS,EAAE;YAC5B,IAAI,EAAE,YAAY;YAClB,QAAQ,EAAE,SAAS;YACnB,IAAI,EAAE,4BAA4B;YAClC,OAAO,EAAE,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC;YACzD,MAAM,EAAE,IAAI;YACZ,GAAG,EAAE,KAAK,CAAC,QAAQ;SACtB,CAAC,CAAC;QACH,OAAO,KAAK,CAAC;IACjB,CAAC;AACL,CAAC;AAED;;;;;;;;;GASG;AACH,MAAM,CAAC,KAAK,UAAU,sBAAsB,CACxC,KAAkB,EAClB,OAAe,EACf,UAAkB;IAElB,IAAI,KAAK,CAAC,cAAc,CAAC,oBAAoB,KAAK,SAAS;QAAE,OAAO;IACpE,IAAI,OAAO,GAAG,KAAK,CAAC,cAAc,CAAC,eAAe,IAAI,UAAU,EAAE,CAAC;QAC/D,MAAM,iBAAiB,CAAC,KAAK,EAAE,OAAO,CAAC,CAAC;IAC5C,CAAC;AACL,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 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 +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":"AAAA,+DAA+D;AAC/D,+DAA+D;AAK/D,OAAO,EAAE,WAAW,EAAE,MAAM,yBAAyB,CAAC;AACtD,OAAO,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AACzC,OAAO,EAAE,gBAAgB,EAAE,MAAM,iBAAiB,CAAC;AAEnD,MAAM,YAAY,GAAuB,MAAM,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC;AAE3D,SAAS,QAAQ,CACb,GAAmB,EACnB,MAAc,EACd,QAAgB,EAChB,IAA2F,EAC3F,OAAe;IAEf,QAAQ,CAAC,GAAG,EAAE,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,SAAS,EAAE,OAAO,CAAC,CAAC;IAC1D,OAAO,YAAY,CAAC;AACxB,CAAC;AAED,SAAS,QAAQ,CACb,GAAmB,EACnB,MAAc,EACd,QAAgB,EAChB,GAAW;IAEX,IAAI,CAAC,GAAG,CAAC,YAAY,CAAC,cAAc,EAAE,CAAC;QACnC,OAAO,QAAQ,CACX,GAAG,EACH,MAAM,EACN,QAAQ,EACR,+BAA+B,EAC/B,+EAA+E,CAClF,CAAC;IACN,CAAC;IAED,MAAM,KAAK,GAAG,GAAG,CAAC,YAAY,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC,UAAU,EAAE,EAAE,CAAC,UAAU,CAAC,KAAK,KAAK,QAAQ,CAAC,CAAC;IAC7F,IAAI,CAAC,KAAK,EAAE,CAAC;QACT,OAAO,QAAQ,CACX,GAAG,EACH,MAAM,EACN,QAAQ,EACR,sBAAsB,EACtB,uBAAuB,QAAQ,oCAAoC,CACtE,CAAC;IACN,CAAC;IAED,MAAM,SAAS,GAAG,GAAG,CAAC,gBAAgB,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;IACrD,IAAI,SAAS,KAAK,SAAS,EAAE,CAAC;QAC1B,OAAO,QAAQ,CACX,GAAG,EACH,MAAM,EACN,QAAQ,EACR,0BAA0B,EAC1B,uBAAuB,QAAQ,sCAAsC,CACxE,CAAC;IACN,CAAC;IAED,MAAM,QAAQ,GAAG,gBAAgB,CAAC,GAAG,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC;IACnD,MAAM,OAAO,GAAG,gBAAgB,CAAC,GAAG,EAAE,SAAS,CAAC,CAAC;IACjD,MAAM,OAAO,GAAG,WAAW,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC;IAC/C,MAAM,KAAK,GAAG,OAAO,CAAC,MAAM,GAAG,CAAC,GAAG,GAAG,CAAC;IACvC,OAAO,OAAO,CAAC,KAAK,CAAC,IAAI,YAAY,CAAC;AAC1C,CAAC;AAED;;;;;;;;;GASG;AACH,MAAM,UAAU,iBAAiB,CAC7B,GAAmB,EACnB,MAAc,EACd,QAAgB;IAEhB,MAAM,QAAQ,GAAG,GAAG,MAAM,IAAI,QAAQ,EAAE,CAAC;IACzC,MAAM,QAAQ,GAAG,GAAG,CAAC,mBAAmB,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;IACvD,IAAI,QAAQ,KAAK,SAAS;QAAE,OAAO,QAAQ,CAAC;IAE5C,MAAM,MAAM,GAAG;QACX,IAAI,OAAO;YACP,OAAO,QAAQ,CAAC,GAAG,EAAE,MAAM,EAAE,QAAQ,EAAE,CAAC,CAAC,CAAC;QAC9C,CAAC;QACD,IAAI,MAAM;YACN,OAAO,GAAG,CAAC,MAAM,CAAC,KAAK,CAAC,KAAK,CAAC,MAAM,CAAC;QACzC,CAAC;KACJ,CAAC;IACF,MAAM,IAAI,GAAG,IAAI,KAAK,CAAC,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,EAAE;QAC1C,GAAG,CAAC,GAAG,EAAE,IAAI,EAAE,QAAQ;YACnB,IAAI,OAAO,IAAI,KAAK,QAAQ,EAAE,CAAC;gBAC3B,MAAM,CAAC,GAAG,MAAM,CAAC,IAAI,CAAC,CAAC;gBACvB,IAAI,MAAM,CAAC,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC;oBAAE,OAAO,QAAQ,CAAC,GAAG,EAAE,MAAM,EAAE,QAAQ,EAAE,CAAC,CAAC,CAAC;YACjF,CAAC;YACD,OAAO,OAAO,CAAC,GAAG,CAAC,GAAG,EAAE,IAAI,EAAE,QAAQ,CAAC,CAAC;QAC5C,CAAC;KACJ,CAA+B,CAAC;IACjC,GAAG,CAAC,mBAAmB,CAAC,GAAG,CAAC,QAAQ,EAAE,IAAI,CAAC,CAAC;IAC5C,OAAO,IAAI,CAAC;AAChB,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 { 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,EAKnB,MAAM,8BAA8B,CAAC;AAwCtC;;;;;;;;;;;;;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,5 +1,6 @@
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
6
  import { makeSecurityBar, makeSecurityExprSeries } from "./security.js";
@@ -11,21 +12,34 @@ function getCtx(name) {
11
12
  }
12
13
  return ctx;
13
14
  }
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
+ }
14
24
  // Dispatch off the runner registry (not `expr !== undefined`) so compiled
15
25
  // output stays robust if the emitted call shape changes: a slotId the compiler
16
26
  // recorded in `manifest.securityExpressions` is always an expression unit.
17
27
  function security(slotId, opts, expr) {
18
28
  const ctx = getCtx("request.security");
29
+ const symbol = resolveSymbol(ctx, opts.symbol);
30
+ const feed = feedKey(symbol, opts.interval);
19
31
  const runner = ctx.securityExprRunners?.get(slotId);
20
32
  if (runner === undefined) {
21
- return makeSecurityBar(ctx, slotId, opts.interval);
33
+ return makeSecurityBar(ctx, slotId, symbol, opts.interval);
22
34
  }
23
35
  if (expr !== undefined) {
24
- const secondary = ctx.secondaryStreams.get(opts.interval);
36
+ const secondary = ctx.secondaryStreams.get(feed);
25
37
  if (secondary !== undefined)
26
38
  captureAndCatchUp(runner, expr, secondary);
27
39
  }
28
- return makeSecurityExprSeries(ctx, runner, opts.interval);
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);
29
43
  }
30
44
  function lowerTf(slotId, opts) {
31
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;AAY/D,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,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,GAAG,CAAC,mBAAmB,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC;IACpD,IAAI,MAAM,KAAK,SAAS,EAAE,CAAC;QACvB,OAAO,eAAe,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,CAAC,QAAQ,CAAC,CAAC;IACvD,CAAC;IACD,IAAI,IAAI,KAAK,SAAS,EAAE,CAAC;QACrB,MAAM,SAAS,GAAG,GAAG,CAAC,gBAAgB,CAAC,GAAG,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;QAC1D,IAAI,SAAS,KAAK,SAAS;YAAE,iBAAiB,CAAC,MAAM,EAAE,IAAI,EAAE,SAAS,CAAC,CAAC;IAC5E,CAAC;IACD,OAAO,sBAAsB,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,CAAC,QAAQ,CAAC,CAAC;AAC9D,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\";\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// 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 runner = ctx.securityExprRunners?.get(slotId);\n if (runner === undefined) {\n return makeSecurityBar(ctx, slotId, opts.interval);\n }\n if (expr !== undefined) {\n const secondary = ctx.secondaryStreams.get(opts.interval);\n if (secondary !== undefined) captureAndCatchUp(runner, expr, secondary);\n }\n return makeSecurityExprSeries(ctx, runner, 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"]}
@@ -13,16 +13,27 @@ import { type SecurityExprRunner } from "./securityExprRunner.js";
13
13
  */
14
14
  export declare function makeNanSecurityBar(): SecurityBar;
15
15
  /**
16
- * 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).
17
28
  *
18
29
  * @since 0.5
19
30
  * @stable
20
31
  * @example
21
- * // const bar = makeSecurityBar(ctx, "slot#0", "1D");
32
+ * // const bar = makeSecurityBar(ctx, "slot#0", undefined, "1D");
22
33
  * const requested = "1D";
23
34
  * void requested;
24
35
  */
25
- 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;
26
37
  /**
27
38
  * Return the main-aligned output series for an HTF expression callsite. The
28
39
  * runner's `output` buffer holds one sampled value per HTF bar; this aligns it
@@ -31,14 +42,20 @@ export declare function makeSecurityBar(ctx: RuntimeContext, slotId: string, int
31
42
  * the OHLCV alignment kernel via {@link getOrAlign}. Capability / interval /
32
43
  * stream fallbacks return an all-NaN series and push a deduped diagnostic,
33
44
  * matching {@link makeSecurityBar}. The returned Proxy identity is cached per
34
- * `slotId|interval` for the bar.
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.
35
52
  *
36
53
  * @since 0.7
37
54
  * @stable
38
55
  * @example
39
- * // const trend = makeSecurityExprSeries(ctx, runner, "1W");
56
+ * // const trend = makeSecurityExprSeries(ctx, runner, "1W", false);
40
57
  * const requested = "1W";
41
58
  * void requested;
42
59
  */
43
- export declare function makeSecurityExprSeries(ctx: RuntimeContext, runner: SecurityExprRunner, interval: string): Series<number>;
60
+ export declare function makeSecurityExprSeries(ctx: RuntimeContext, runner: SecurityExprRunner, feed: string, isDifferentSymbol: boolean): Series<number>;
44
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,EAAE,MAAM,EAAE,MAAM,8BAA8B,CAAC;AAExE,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;AAwHD;;;;;;;;;GASG;AACH,wBAAgB,eAAe,CAC3B,GAAG,EAAE,cAAc,EACnB,MAAM,EAAE,MAAM,EACd,QAAQ,EAAE,MAAM,GACjB,WAAW,CA2Cb;AA+CD;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAgB,sBAAsB,CAClC,GAAG,EAAE,cAAc,EACnB,MAAM,EAAE,kBAAkB,EAC1B,QAAQ,EAAE,MAAM,GACjB,MAAM,CAAC,MAAM,CAAC,CAmBhB"}
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,5 +1,6 @@
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
6
  import { ascendingValues } from "./securityExprRunner.js";
@@ -55,11 +56,11 @@ function seriesAscending(stream, sourceKey) {
55
56
  }
56
57
  return values;
57
58
  }
58
- function alignmentKey(slotId, interval, sourceKey) {
59
- return `${slotId}|${interval}|${sourceKey}`;
59
+ function alignmentKey(slotId, feed, sourceKey) {
60
+ return `${slotId}|${feed}|${sourceKey}`;
60
61
  }
61
- function alignedSeries(ctx, slotId, interval, sourceKey, secondary) {
62
- const key = alignmentKey(slotId, interval, sourceKey);
62
+ function alignedSeries(ctx, slotId, feed, sourceKey, secondary) {
63
+ const key = alignmentKey(slotId, feed, sourceKey);
63
64
  const existing = ctx.requestSecurityAlignments.get(key);
64
65
  if (existing !== undefined)
65
66
  return existing;
@@ -101,13 +102,13 @@ function makeAlignedSeriesProxy(ctx, produce) {
101
102
  },
102
103
  });
103
104
  }
104
- function makeAlignedNumberSeries(ctx, slotId, interval, sourceKey, secondary) {
105
- return makeAlignedSeriesProxy(ctx, () => alignedSeries(ctx, slotId, interval, sourceKey, secondary));
105
+ function makeAlignedNumberSeries(ctx, slotId, feed, sourceKey, secondary) {
106
+ return makeAlignedSeriesProxy(ctx, () => alignedSeries(ctx, slotId, feed, sourceKey, secondary));
106
107
  }
107
- function makeLiveSecurityBar(ctx, slotId, interval, secondary) {
108
+ function makeLiveSecurityBar(ctx, slotId, feed, interval, secondary) {
108
109
  const numeric = new Map();
109
110
  for (const key of NUMERIC_SOURCE_KEYS) {
110
- numeric.set(key, makeAlignedNumberSeries(ctx, slotId, interval, key, secondary));
111
+ numeric.set(key, makeAlignedNumberSeries(ctx, slotId, feed, key, secondary));
111
112
  }
112
113
  return Object.freeze({
113
114
  time: numeric.get("time") ?? makeSeries(Number.NaN),
@@ -124,57 +125,78 @@ function makeLiveSecurityBar(ctx, slotId, interval, secondary) {
124
125
  interval: makeConstantStringSeries(interval),
125
126
  });
126
127
  }
127
- function fallbackNaN(ctx, cacheKey, slotId, interval, code, message) {
128
- 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);
129
134
  const bar = makeNanSecurityBar();
130
135
  ctx.requestSecurityBars.set(cacheKey, bar);
131
136
  return bar;
132
137
  }
133
138
  /**
134
- * 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).
135
151
  *
136
152
  * @since 0.5
137
153
  * @stable
138
154
  * @example
139
- * // const bar = makeSecurityBar(ctx, "slot#0", "1D");
155
+ * // const bar = makeSecurityBar(ctx, "slot#0", undefined, "1D");
140
156
  * const requested = "1D";
141
157
  * void requested;
142
158
  */
143
- export function makeSecurityBar(ctx, slotId, interval) {
144
- const cacheKey = `${slotId}|${interval}`;
159
+ export function makeSecurityBar(ctx, slotId, symbol, interval) {
160
+ const feed = feedKey(symbol, interval);
161
+ const cacheKey = `${slotId}|${feed}`;
145
162
  const existing = ctx.requestSecurityBars.get(cacheKey);
146
163
  if (existing !== undefined)
147
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
+ }
148
170
  if (!ctx.capabilities.multiTimeframe) {
149
- 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");
150
172
  }
151
173
  const known = ctx.capabilities.intervals.some((descriptor) => descriptor.value === interval);
152
174
  if (!known) {
153
- 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`);
154
176
  }
155
- const secondary = ctx.secondaryStreams.get(interval);
177
+ const secondary = ctx.secondaryStreams.get(feed);
156
178
  if (secondary === undefined) {
157
- 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`);
158
180
  }
159
- const bar = makeLiveSecurityBar(ctx, slotId, interval, secondary);
181
+ const bar = makeLiveSecurityBar(ctx, slotId, feed, interval, secondary);
160
182
  ctx.requestSecurityBars.set(cacheKey, bar);
161
183
  return bar;
162
184
  }
163
185
  function makeNanNumberSeries() {
164
186
  return makeSeries(Number.NaN);
165
187
  }
166
- function resolveSecondaryOrDiagnose(ctx, slotId, interval) {
188
+ function resolveSecondaryOrDiagnose(ctx, slotId, feed, interval) {
167
189
  if (!ctx.capabilities.multiTimeframe) {
168
- pushOnce(ctx, "multi-timeframe-not-supported", slotId, interval, "security", "Adapter declares multiTimeframe: false; request.security returns NaN");
190
+ pushOnce(ctx, "multi-timeframe-not-supported", slotId, feed, "security", "Adapter declares multiTimeframe: false; request.security returns NaN");
169
191
  return undefined;
170
192
  }
171
193
  if (!ctx.capabilities.intervals.some((descriptor) => descriptor.value === interval)) {
172
- pushOnce(ctx, "unsupported-interval", slotId, interval, "security", `Requested interval "${interval}" is not in Capabilities.intervals`);
194
+ pushOnce(ctx, "unsupported-interval", slotId, feed, "security", `Requested interval "${interval}" is not in Capabilities.intervals`);
173
195
  return undefined;
174
196
  }
175
- const secondary = ctx.secondaryStreams.get(interval);
197
+ const secondary = ctx.secondaryStreams.get(feed);
176
198
  if (secondary === undefined) {
177
- pushOnce(ctx, "unknown-secondary-stream", slotId, interval, "security", `Requested interval "${interval}" has no registered secondary stream`);
199
+ pushOnce(ctx, "unknown-secondary-stream", slotId, feed, "security", `Requested interval "${interval}" has no registered secondary stream`);
178
200
  }
179
201
  return secondary;
180
202
  }
@@ -186,22 +208,35 @@ function resolveSecondaryOrDiagnose(ctx, slotId, interval) {
186
208
  * the OHLCV alignment kernel via {@link getOrAlign}. Capability / interval /
187
209
  * stream fallbacks return an all-NaN series and push a deduped diagnostic,
188
210
  * matching {@link makeSecurityBar}. The returned Proxy identity is cached per
189
- * `slotId|interval` for the bar.
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.
190
218
  *
191
219
  * @since 0.7
192
220
  * @stable
193
221
  * @example
194
- * // const trend = makeSecurityExprSeries(ctx, runner, "1W");
222
+ * // const trend = makeSecurityExprSeries(ctx, runner, "1W", false);
195
223
  * const requested = "1W";
196
224
  * void requested;
197
225
  */
198
- export function makeSecurityExprSeries(ctx, runner, interval) {
199
- const cacheKey = `${runner.slotId}|${interval}`;
226
+ export function makeSecurityExprSeries(ctx, runner, feed, isDifferentSymbol) {
227
+ const cacheKey = `${runner.slotId}|${feed}`;
200
228
  const cache = ctx.requestSecurityExprSeries;
201
229
  const existing = cache?.get(cacheKey);
202
230
  if (existing !== undefined)
203
231
  return existing;
204
- const secondary = resolveSecondaryOrDiagnose(ctx, runner.slotId, interval);
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);
205
240
  const series = secondary === undefined
206
241
  ? makeNanNumberSeries()
207
242
  : makeAlignedSeriesProxy(ctx, () => getOrAlign(ascendingBarsFor(ctx, secondary), ascendingValues(runner.output), ascendingBarsFor(ctx, ctx.stream)));