pineforge-codegen 0.7.2__tar.gz → 0.7.4__tar.gz

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 (391) hide show
  1. pineforge_codegen-0.7.4/.github/dependabot.yml +20 -0
  2. {pineforge_codegen-0.7.2 → pineforge_codegen-0.7.4}/PKG-INFO +1 -1
  3. pineforge_codegen-0.7.4/VERSION +1 -0
  4. {pineforge_codegen-0.7.2 → pineforge_codegen-0.7.4}/gate/glue.py +3 -3
  5. {pineforge_codegen-0.7.2 → pineforge_codegen-0.7.4}/pineforge_codegen/__init__.py +39 -0
  6. {pineforge_codegen-0.7.2 → pineforge_codegen-0.7.4}/pineforge_codegen/codegen/base.py +87 -10
  7. {pineforge_codegen-0.7.2 → pineforge_codegen-0.7.4}/pineforge_codegen/codegen/input.py +142 -1
  8. {pineforge_codegen-0.7.2 → pineforge_codegen-0.7.4}/pineforge_codegen/codegen/visit_call.py +5 -0
  9. {pineforge_codegen-0.7.2 → pineforge_codegen-0.7.4}/pineforge_codegen/support_checker.py +62 -19
  10. {pineforge_codegen-0.7.2 → pineforge_codegen-0.7.4}/scripts/worker-template.mjs +21 -0
  11. pineforge_codegen-0.7.4/tests/gate-corpus/err/divergent_last_bar_index.pine +7 -0
  12. pineforge_codegen-0.7.4/tests/gate-corpus/err/divergent_time_close.pine +9 -0
  13. pineforge_codegen-0.7.4/tests/gate-corpus/ok/validation__max-bars-back-function-call-deep-history-01.pine +23 -0
  14. pineforge_codegen-0.7.4/tests/test_extract_inputs.py +107 -0
  15. pineforge_codegen-0.7.4/tests/test_glue_smoke.py +43 -0
  16. {pineforge_codegen-0.7.2 → pineforge_codegen-0.7.4}/tests/test_official_surface.py +40 -0
  17. {pineforge_codegen-0.7.2 → pineforge_codegen-0.7.4}/tests/test_support_checker.py +78 -8
  18. pineforge_codegen-0.7.4/tests/test_support_checker_syminfo_gap_fields.py +120 -0
  19. pineforge_codegen-0.7.2/.github/dependabot.yml +0 -8
  20. pineforge_codegen-0.7.2/VERSION +0 -1
  21. pineforge_codegen-0.7.2/tests/test_support_checker_syminfo_gap_fields.py +0 -71
  22. {pineforge_codegen-0.7.2 → pineforge_codegen-0.7.4}/.github/workflows/gate.yml +0 -0
  23. {pineforge_codegen-0.7.2 → pineforge_codegen-0.7.4}/.github/workflows/publish-pyodide.yml +0 -0
  24. {pineforge_codegen-0.7.2 → pineforge_codegen-0.7.4}/.github/workflows/release.yml +0 -0
  25. {pineforge_codegen-0.7.2 → pineforge_codegen-0.7.4}/.github/workflows/test.yml +0 -0
  26. {pineforge_codegen-0.7.2 → pineforge_codegen-0.7.4}/.gitignore +0 -0
  27. {pineforge_codegen-0.7.2 → pineforge_codegen-0.7.4}/CLAUDE.md +0 -0
  28. {pineforge_codegen-0.7.2 → pineforge_codegen-0.7.4}/LEGAL.md +0 -0
  29. {pineforge_codegen-0.7.2 → pineforge_codegen-0.7.4}/LICENSE +0 -0
  30. {pineforge_codegen-0.7.2 → pineforge_codegen-0.7.4}/PYODIDE_TARGET +0 -0
  31. {pineforge_codegen-0.7.2 → pineforge_codegen-0.7.4}/README.md +0 -0
  32. {pineforge_codegen-0.7.2 → pineforge_codegen-0.7.4}/docs/codegen-coverage-gaps.md +0 -0
  33. {pineforge_codegen-0.7.2 → pineforge_codegen-0.7.4}/gate/compare.mjs +0 -0
  34. {pineforge_codegen-0.7.2 → pineforge_codegen-0.7.4}/gate/oracle.py +0 -0
  35. {pineforge_codegen-0.7.2 → pineforge_codegen-0.7.4}/gate/run-gate.mjs +0 -0
  36. {pineforge_codegen-0.7.2 → pineforge_codegen-0.7.4}/gate/selftest.mjs +0 -0
  37. {pineforge_codegen-0.7.2 → pineforge_codegen-0.7.4}/npm/README.md +0 -0
  38. {pineforge_codegen-0.7.2 → pineforge_codegen-0.7.4}/npm/index.mjs +0 -0
  39. {pineforge_codegen-0.7.2 → pineforge_codegen-0.7.4}/npm/package.json +0 -0
  40. {pineforge_codegen-0.7.2 → pineforge_codegen-0.7.4}/package-lock.json +0 -0
  41. {pineforge_codegen-0.7.2 → pineforge_codegen-0.7.4}/package.json +0 -0
  42. {pineforge_codegen-0.7.2 → pineforge_codegen-0.7.4}/pineforge_codegen/analyzer/__init__.py +0 -0
  43. {pineforge_codegen-0.7.2 → pineforge_codegen-0.7.4}/pineforge_codegen/analyzer/base.py +0 -0
  44. {pineforge_codegen-0.7.2 → pineforge_codegen-0.7.4}/pineforge_codegen/analyzer/call_handlers.py +0 -0
  45. {pineforge_codegen-0.7.2 → pineforge_codegen-0.7.4}/pineforge_codegen/analyzer/contracts.py +0 -0
  46. {pineforge_codegen-0.7.2 → pineforge_codegen-0.7.4}/pineforge_codegen/analyzer/diagnostics.py +0 -0
  47. {pineforge_codegen-0.7.2 → pineforge_codegen-0.7.4}/pineforge_codegen/analyzer/tables.py +0 -0
  48. {pineforge_codegen-0.7.2 → pineforge_codegen-0.7.4}/pineforge_codegen/analyzer/types.py +0 -0
  49. {pineforge_codegen-0.7.2 → pineforge_codegen-0.7.4}/pineforge_codegen/ast_nodes.py +0 -0
  50. {pineforge_codegen-0.7.2 → pineforge_codegen-0.7.4}/pineforge_codegen/codegen/__init__.py +0 -0
  51. {pineforge_codegen-0.7.2 → pineforge_codegen-0.7.4}/pineforge_codegen/codegen/emit_top.py +0 -0
  52. {pineforge_codegen-0.7.2 → pineforge_codegen-0.7.4}/pineforge_codegen/codegen/helpers.py +0 -0
  53. {pineforge_codegen-0.7.2 → pineforge_codegen-0.7.4}/pineforge_codegen/codegen/helpers_syminfo.py +0 -0
  54. {pineforge_codegen-0.7.2 → pineforge_codegen-0.7.4}/pineforge_codegen/codegen/security.py +0 -0
  55. {pineforge_codegen-0.7.2 → pineforge_codegen-0.7.4}/pineforge_codegen/codegen/ta.py +0 -0
  56. {pineforge_codegen-0.7.2 → pineforge_codegen-0.7.4}/pineforge_codegen/codegen/tables.py +0 -0
  57. {pineforge_codegen-0.7.2 → pineforge_codegen-0.7.4}/pineforge_codegen/codegen/types.py +0 -0
  58. {pineforge_codegen-0.7.2 → pineforge_codegen-0.7.4}/pineforge_codegen/codegen/visit_expr.py +0 -0
  59. {pineforge_codegen-0.7.2 → pineforge_codegen-0.7.4}/pineforge_codegen/codegen/visit_stmt.py +0 -0
  60. {pineforge_codegen-0.7.2 → pineforge_codegen-0.7.4}/pineforge_codegen/errors.py +0 -0
  61. {pineforge_codegen-0.7.2 → pineforge_codegen-0.7.4}/pineforge_codegen/lexer.py +0 -0
  62. {pineforge_codegen-0.7.2 → pineforge_codegen-0.7.4}/pineforge_codegen/parser.py +0 -0
  63. {pineforge_codegen-0.7.2 → pineforge_codegen-0.7.4}/pineforge_codegen/pragmas.py +0 -0
  64. {pineforge_codegen-0.7.2 → pineforge_codegen-0.7.4}/pineforge_codegen/signatures.py +0 -0
  65. {pineforge_codegen-0.7.2 → pineforge_codegen-0.7.4}/pineforge_codegen/symbols.py +0 -0
  66. {pineforge_codegen-0.7.2 → pineforge_codegen-0.7.4}/pineforge_codegen/tokens.py +0 -0
  67. {pineforge_codegen-0.7.2 → pineforge_codegen-0.7.4}/pineforge_codegen/tv_input_choices.py +0 -0
  68. {pineforge_codegen-0.7.2 → pineforge_codegen-0.7.4}/pyproject.toml +0 -0
  69. {pineforge_codegen-0.7.2 → pineforge_codegen-0.7.4}/scripts/build-npm-package.mjs +0 -0
  70. {pineforge_codegen-0.7.2 → pineforge_codegen-0.7.4}/scripts/dump-tables.py +0 -0
  71. {pineforge_codegen-0.7.2 → pineforge_codegen-0.7.4}/tests/__init__.py +0 -0
  72. {pineforge_codegen-0.7.2 → pineforge_codegen-0.7.4}/tests/_compile.py +0 -0
  73. {pineforge_codegen-0.7.2 → pineforge_codegen-0.7.4}/tests/gate-corpus/err/chart_bg_color.pine +0 -0
  74. {pineforge_codegen-0.7.2 → pineforge_codegen-0.7.4}/tests/gate-corpus/err/const_ns_plot_style_free.pine +0 -0
  75. {pineforge_codegen-0.7.2 → pineforge_codegen-0.7.4}/tests/gate-corpus/err/const_ns_shape_free.pine +0 -0
  76. {pineforge_codegen-0.7.2 → pineforge_codegen-0.7.4}/tests/gate-corpus/err/export_func.pine +0 -0
  77. {pineforge_codegen-0.7.2 → pineforge_codegen-0.7.4}/tests/gate-corpus/err/footprint_new.pine +0 -0
  78. {pineforge_codegen-0.7.2 → pineforge_codegen-0.7.4}/tests/gate-corpus/err/hard_reject_dividends.pine +0 -0
  79. {pineforge_codegen-0.7.2 → pineforge_codegen-0.7.4}/tests/gate-corpus/err/matrix_unknown_elem.pine +0 -0
  80. {pineforge_codegen-0.7.2 → pineforge_codegen-0.7.4}/tests/gate-corpus/err/multi_error_one_line.pine +0 -0
  81. {pineforge_codegen-0.7.2 → pineforge_codegen-0.7.4}/tests/gate-corpus/err/sec_tf_invalid.pine +0 -0
  82. {pineforge_codegen-0.7.2 → pineforge_codegen-0.7.4}/tests/gate-corpus/err/unknown_color.pine +0 -0
  83. {pineforge_codegen-0.7.2 → pineforge_codegen-0.7.4}/tests/gate-corpus/err/unknown_math.pine +0 -0
  84. {pineforge_codegen-0.7.2 → pineforge_codegen-0.7.4}/tests/gate-corpus/err/unknown_str.pine +0 -0
  85. {pineforge_codegen-0.7.2 → pineforge_codegen-0.7.4}/tests/gate-corpus/err/unknown_strategy_fn.pine +0 -0
  86. {pineforge_codegen-0.7.2 → pineforge_codegen-0.7.4}/tests/gate-corpus/err/unknown_syminfo.pine +0 -0
  87. {pineforge_codegen-0.7.2 → pineforge_codegen-0.7.4}/tests/gate-corpus/err/unknown_ta.pine +0 -0
  88. {pineforge_codegen-0.7.2 → pineforge_codegen-0.7.4}/tests/gate-corpus/ok/AAPL__session-ismarket-nyse-rth-01.pine +0 -0
  89. {pineforge_codegen-0.7.2 → pineforge_codegen-0.7.4}/tests/gate-corpus/ok/AAPL__time-tradingday-daily-reset-counter-01.pine +0 -0
  90. {pineforge_codegen-0.7.2 → pineforge_codegen-0.7.4}/tests/gate-corpus/ok/QQQ__session-ispremarket-nasdaq-01.pine +0 -0
  91. {pineforge_codegen-0.7.2 → pineforge_codegen-0.7.4}/tests/gate-corpus/ok/SPY__session-firstbar-vwap-anchor-01.pine +0 -0
  92. {pineforge_codegen-0.7.2 → pineforge_codegen-0.7.4}/tests/gate-corpus/ok/SPY__session-lastbar-flatten-01.pine +0 -0
  93. {pineforge_codegen-0.7.2 → pineforge_codegen-0.7.4}/tests/gate-corpus/ok/crypto-htf__mtf-htf-monthly-ema-cross-01.pine +0 -0
  94. {pineforge_codegen-0.7.2 → pineforge_codegen-0.7.4}/tests/gate-corpus/ok/crypto-leverage__leverage-margin-call-perp-5x-01.pine +0 -0
  95. {pineforge_codegen-0.7.2 → pineforge_codegen-0.7.4}/tests/gate-corpus/ok/forex__symbol-fx-5dp-eurusd-01.pine +0 -0
  96. {pineforge_codegen-0.7.2 → pineforge_codegen-0.7.4}/tests/gate-corpus/ok/futures__symbol-futures-pointvalue-es-01.pine +0 -0
  97. {pineforge_codegen-0.7.2 → pineforge_codegen-0.7.4}/tests/gate-corpus/ok/tutorial__macd__strategy.pine +0 -0
  98. {pineforge_codegen-0.7.2 → pineforge_codegen-0.7.4}/tests/gate-corpus/ok/tutorial__mtf__strategy_htf.pine +0 -0
  99. {pineforge_codegen-0.7.2 → pineforge_codegen-0.7.4}/tests/gate-corpus/ok/tutorial__mtf__strategy_ltf.pine +0 -0
  100. {pineforge_codegen-0.7.2 → pineforge_codegen-0.7.4}/tests/gate-corpus/ok/us-equity__symbol-equity-rth-gaps-aapl-01.pine +0 -0
  101. {pineforge_codegen-0.7.2 → pineforge_codegen-0.7.4}/tests/gate-corpus/ok/us-equity__us-equity-exchange-tz-intraday-cap-01.pine +0 -0
  102. {pineforge_codegen-0.7.2 → pineforge_codegen-0.7.4}/tests/gate-corpus/ok/validation__analyzer-parity-choch-bos-isolator-01.pine +0 -0
  103. {pineforge_codegen-0.7.2 → pineforge_codegen-0.7.4}/tests/gate-corpus/ok/validation__analyzer-parity-edge-margin-50-pct-01.pine +0 -0
  104. {pineforge_codegen-0.7.2 → pineforge_codegen-0.7.4}/tests/gate-corpus/ok/validation__analyzer-parity-percent-of-equity-sizing-01.pine +0 -0
  105. {pineforge_codegen-0.7.2 → pineforge_codegen-0.7.4}/tests/gate-corpus/ok/validation__analyzer-parity-small-equity-fraction-01.pine +0 -0
  106. {pineforge_codegen-0.7.2 → pineforge_codegen-0.7.4}/tests/gate-corpus/ok/validation__analyzer-parity-stop-limit-timing-01.pine +0 -0
  107. {pineforge_codegen-0.7.2 → pineforge_codegen-0.7.4}/tests/gate-corpus/ok/validation__analyzer-self-test-multi-mode-01.pine +0 -0
  108. {pineforge_codegen-0.7.2 → pineforge_codegen-0.7.4}/tests/gate-corpus/ok/validation__anomaly-equity-mirror-strategy-equity-01.pine +0 -0
  109. {pineforge_codegen-0.7.2 → pineforge_codegen-0.7.4}/tests/gate-corpus/ok/validation__barstate-isconfirmed-magnifier-off-01b.pine +0 -0
  110. {pineforge_codegen-0.7.2 → pineforge_codegen-0.7.4}/tests/gate-corpus/ok/validation__barstate-isconfirmed-magnifier-on-01a.pine +0 -0
  111. {pineforge_codegen-0.7.2 → pineforge_codegen-0.7.4}/tests/gate-corpus/ok/validation__bracket-atr-trail-series-int-points-01.pine +0 -0
  112. {pineforge_codegen-0.7.2 → pineforge_codegen-0.7.4}/tests/gate-corpus/ok/validation__bracket-atr-trailing-stop-state-01.pine +0 -0
  113. {pineforge_codegen-0.7.2 → pineforge_codegen-0.7.4}/tests/gate-corpus/ok/validation__bracket-entry-exit-same-pass-attach-01.pine +0 -0
  114. {pineforge_codegen-0.7.2 → pineforge_codegen-0.7.4}/tests/gate-corpus/ok/validation__bracket-exit-stop-limit-trail-same-bar-01.pine +0 -0
  115. {pineforge_codegen-0.7.2 → pineforge_codegen-0.7.4}/tests/gate-corpus/ok/validation__bracket-exit-three-way-set-once-entry-01.pine +0 -0
  116. {pineforge_codegen-0.7.2 → pineforge_codegen-0.7.4}/tests/gate-corpus/ok/validation__bracket-exit-tp-sl-fixed-01.pine +0 -0
  117. {pineforge_codegen-0.7.2 → pineforge_codegen-0.7.4}/tests/gate-corpus/ok/validation__bracket-narrow-stop-limit-with-trail8-01.pine +0 -0
  118. {pineforge_codegen-0.7.2 → pineforge_codegen-0.7.4}/tests/gate-corpus/ok/validation__bracket-partial-exit-qty-percent-01.pine +0 -0
  119. {pineforge_codegen-0.7.2 → pineforge_codegen-0.7.4}/tests/gate-corpus/ok/validation__bracket-same-id-exit-replace-01.pine +0 -0
  120. {pineforge_codegen-0.7.2 → pineforge_codegen-0.7.4}/tests/gate-corpus/ok/validation__bracket-tp-sl-oca-reduce-isolate-01.pine +0 -0
  121. {pineforge_codegen-0.7.2 → pineforge_codegen-0.7.4}/tests/gate-corpus/ok/validation__bracket-trail-points-no-offset-explicit-01.pine +0 -0
  122. {pineforge_codegen-0.7.2 → pineforge_codegen-0.7.4}/tests/gate-corpus/ok/validation__bracket-trail-points-with-offset-only-01.pine +0 -0
  123. {pineforge_codegen-0.7.2 → pineforge_codegen-0.7.4}/tests/gate-corpus/ok/validation__bracket-trailing-activation-offset-path-01.pine +0 -0
  124. {pineforge_codegen-0.7.2 → pineforge_codegen-0.7.4}/tests/gate-corpus/ok/validation__cap-max-intraday-filled-orders-isolate-01.pine +0 -0
  125. {pineforge_codegen-0.7.2 → pineforge_codegen-0.7.4}/tests/gate-corpus/ok/validation__cap-risk-gates-allow-max-intraday-01.pine +0 -0
  126. {pineforge_codegen-0.7.2 → pineforge_codegen-0.7.4}/tests/gate-corpus/ok/validation__composite-4emarsi-integration-01.pine +0 -0
  127. {pineforge_codegen-0.7.2 → pineforge_codegen-0.7.4}/tests/gate-corpus/ok/validation__composite-4emarsi-quad-ema-stack-01.pine +0 -0
  128. {pineforge_codegen-0.7.2 → pineforge_codegen-0.7.4}/tests/gate-corpus/ok/validation__composite-4emarsi-rsi-pullback-latch-01.pine +0 -0
  129. {pineforge_codegen-0.7.2 → pineforge_codegen-0.7.4}/tests/gate-corpus/ok/validation__composite-4emarsi-session-window-nbar-exit-01.pine +0 -0
  130. {pineforge_codegen-0.7.2 → pineforge_codegen-0.7.4}/tests/gate-corpus/ok/validation__composite-boscurv-integration-01.pine +0 -0
  131. {pineforge_codegen-0.7.2 → pineforge_codegen-0.7.4}/tests/gate-corpus/ok/validation__composite-boscurv-linreg-slope-channel-01.pine +0 -0
  132. {pineforge_codegen-0.7.2 → pineforge_codegen-0.7.4}/tests/gate-corpus/ok/validation__composite-boscurv-pivot-bos-trigger-01.pine +0 -0
  133. {pineforge_codegen-0.7.2 → pineforge_codegen-0.7.4}/tests/gate-corpus/ok/validation__composite-bracket-cap-range-pending-stop-01.pine +0 -0
  134. {pineforge_codegen-0.7.2 → pineforge_codegen-0.7.4}/tests/gate-corpus/ok/validation__composite-ies-adx-regime-classify-01.pine +0 -0
  135. {pineforge_codegen-0.7.2 → pineforge_codegen-0.7.4}/tests/gate-corpus/ok/validation__composite-ies-bb-kc-squeeze-release-01.pine +0 -0
  136. {pineforge_codegen-0.7.2 → pineforge_codegen-0.7.4}/tests/gate-corpus/ok/validation__composite-ies-cooldown-daily-cap-01.pine +0 -0
  137. {pineforge_codegen-0.7.2 → pineforge_codegen-0.7.4}/tests/gate-corpus/ok/validation__composite-ies-equity-feedback-sizing-01.pine +0 -0
  138. {pineforge_codegen-0.7.2 → pineforge_codegen-0.7.4}/tests/gate-corpus/ok/validation__composite-ies-integration-01.pine +0 -0
  139. {pineforge_codegen-0.7.2 → pineforge_codegen-0.7.4}/tests/gate-corpus/ok/validation__composite-ies-pivot-liquidity-sweep-01.pine +0 -0
  140. {pineforge_codegen-0.7.2 → pineforge_codegen-0.7.4}/tests/gate-corpus/ok/validation__composite-ies-pressure-gauge-01.pine +0 -0
  141. {pineforge_codegen-0.7.2 → pineforge_codegen-0.7.4}/tests/gate-corpus/ok/validation__composite-ies-rsi-macd-momentum-01.pine +0 -0
  142. {pineforge_codegen-0.7.2 → pineforge_codegen-0.7.4}/tests/gate-corpus/ok/validation__composite-ies-three-ema-bias-score-01.pine +0 -0
  143. {pineforge_codegen-0.7.2 → pineforge_codegen-0.7.4}/tests/gate-corpus/ok/validation__composite-kanuck-calc-on-every-tick-01.pine +0 -0
  144. {pineforge_codegen-0.7.2 → pineforge_codegen-0.7.4}/tests/gate-corpus/ok/validation__composite-kanuck-integration-01.pine +0 -0
  145. {pineforge_codegen-0.7.2 → pineforge_codegen-0.7.4}/tests/gate-corpus/ok/validation__composite-kanuck-kama-state-recurrence-01.pine +0 -0
  146. {pineforge_codegen-0.7.2 → pineforge_codegen-0.7.4}/tests/gate-corpus/ok/validation__composite-kanuck-max-bars-back-500-01.pine +0 -0
  147. {pineforge_codegen-0.7.2 → pineforge_codegen-0.7.4}/tests/gate-corpus/ok/validation__composite-kkb-ema-atr-breakout-band-01.pine +0 -0
  148. {pineforge_codegen-0.7.2 → pineforge_codegen-0.7.4}/tests/gate-corpus/ok/validation__composite-kkb-integration-01.pine +0 -0
  149. {pineforge_codegen-0.7.2 → pineforge_codegen-0.7.4}/tests/gate-corpus/ok/validation__composite-kkb-kalman-filter-1d-01.pine +0 -0
  150. {pineforge_codegen-0.7.2 → pineforge_codegen-0.7.4}/tests/gate-corpus/ok/validation__composite-kkb-margin-100-pct-01.pine +0 -0
  151. {pineforge_codegen-0.7.2 → pineforge_codegen-0.7.4}/tests/gate-corpus/ok/validation__composite-liqsweep-integration-01.pine +0 -0
  152. {pineforge_codegen-0.7.2 → pineforge_codegen-0.7.4}/tests/gate-corpus/ok/validation__composite-liqsweep-pivot-hh-ll-01.pine +0 -0
  153. {pineforge_codegen-0.7.2 → pineforge_codegen-0.7.4}/tests/gate-corpus/ok/validation__composite-liqsweep-wait-one-continuation-01.pine +0 -0
  154. {pineforge_codegen-0.7.2 → pineforge_codegen-0.7.4}/tests/gate-corpus/ok/validation__composite-liqsweep-wick-pierce-close-back-01.pine +0 -0
  155. {pineforge_codegen-0.7.2 → pineforge_codegen-0.7.4}/tests/gate-corpus/ok/validation__composite-marketshift-integration-01.pine +0 -0
  156. {pineforge_codegen-0.7.2 → pineforge_codegen-0.7.4}/tests/gate-corpus/ok/validation__composite-marketshift-pivot-state-machine-01.pine +0 -0
  157. {pineforge_codegen-0.7.2 → pineforge_codegen-0.7.4}/tests/gate-corpus/ok/validation__composite-marketshift-rolling-highest-lowest-01.pine +0 -0
  158. {pineforge_codegen-0.7.2 → pineforge_codegen-0.7.4}/tests/gate-corpus/ok/validation__composite-marketshift-state-edge-detector-01.pine +0 -0
  159. {pineforge_codegen-0.7.2 → pineforge_codegen-0.7.4}/tests/gate-corpus/ok/validation__composite-scalping-fast-ma-cross-trigger-01.pine +0 -0
  160. {pineforge_codegen-0.7.2 → pineforge_codegen-0.7.4}/tests/gate-corpus/ok/validation__composite-scalping-integration-01.pine +0 -0
  161. {pineforge_codegen-0.7.2 → pineforge_codegen-0.7.4}/tests/gate-corpus/ok/validation__composite-scalping-tight-tp-sl-points-01.pine +0 -0
  162. {pineforge_codegen-0.7.2 → pineforge_codegen-0.7.4}/tests/gate-corpus/ok/validation__composite-trendmaster-integration-01.pine +0 -0
  163. {pineforge_codegen-0.7.2 → pineforge_codegen-0.7.4}/tests/gate-corpus/ok/validation__composite-trendmaster-line-new-projection-01.pine +0 -0
  164. {pineforge_codegen-0.7.2 → pineforge_codegen-0.7.4}/tests/gate-corpus/ok/validation__composite-trendmaster-pivot-anchored-bracket-01.pine +0 -0
  165. {pineforge_codegen-0.7.2 → pineforge_codegen-0.7.4}/tests/gate-corpus/ok/validation__composite-trendmaster-three-tier-ema-state-01.pine +0 -0
  166. {pineforge_codegen-0.7.2 → pineforge_codegen-0.7.4}/tests/gate-corpus/ok/validation__composite-trendmaster-trend-momentum-structure-gate-01.pine +0 -0
  167. {pineforge_codegen-0.7.2 → pineforge_codegen-0.7.4}/tests/gate-corpus/ok/validation__composite-vcp-cumulative-volume-delta-01.pine +0 -0
  168. {pineforge_codegen-0.7.2 → pineforge_codegen-0.7.4}/tests/gate-corpus/ok/validation__composite-vcp-fvg-active-zones-01.pine +0 -0
  169. {pineforge_codegen-0.7.2 → pineforge_codegen-0.7.4}/tests/gate-corpus/ok/validation__composite-vcp-integration-01.pine +0 -0
  170. {pineforge_codegen-0.7.2 → pineforge_codegen-0.7.4}/tests/gate-corpus/ok/validation__composite-vcp-manual-adx-regime-01.pine +0 -0
  171. {pineforge_codegen-0.7.2 → pineforge_codegen-0.7.4}/tests/gate-corpus/ok/validation__composite-vcp-pivot-strength-5-01.pine +0 -0
  172. {pineforge_codegen-0.7.2 → pineforge_codegen-0.7.4}/tests/gate-corpus/ok/validation__composite-vcp-rsi-smooth-divergence-01.pine +0 -0
  173. {pineforge_codegen-0.7.2 → pineforge_codegen-0.7.4}/tests/gate-corpus/ok/validation__composite-vcp-session-tz-newyork-01.pine +0 -0
  174. {pineforge_codegen-0.7.2 → pineforge_codegen-0.7.4}/tests/gate-corpus/ok/validation__composite-vcp-vol-zscore-anomaly-01.pine +0 -0
  175. {pineforge_codegen-0.7.2 → pineforge_codegen-0.7.4}/tests/gate-corpus/ok/validation__composite-wunderscalper-alert-templates-01.pine +0 -0
  176. {pineforge_codegen-0.7.2 → pineforge_codegen-0.7.4}/tests/gate-corpus/ok/validation__composite-wunderscalper-explicit-reverse-01.pine +0 -0
  177. {pineforge_codegen-0.7.2 → pineforge_codegen-0.7.4}/tests/gate-corpus/ok/validation__composite-wunderscalper-integration-01.pine +0 -0
  178. {pineforge_codegen-0.7.2 → pineforge_codegen-0.7.4}/tests/gate-corpus/ok/validation__input-source-runtime-override-high-01.pine +0 -0
  179. {pineforge_codegen-0.7.2 → pineforge_codegen-0.7.4}/tests/gate-corpus/ok/validation__input-source-subscript-hl2-01.pine +0 -0
  180. {pineforge_codegen-0.7.2 → pineforge_codegen-0.7.4}/tests/gate-corpus/ok/validation__ltf-bool-array-bull-majority-01.pine +0 -0
  181. {pineforge_codegen-0.7.2 → pineforge_codegen-0.7.4}/tests/gate-corpus/ok/validation__ltf-numeric-float-ratio15-01.pine +0 -0
  182. {pineforge_codegen-0.7.2 → pineforge_codegen-0.7.4}/tests/gate-corpus/ok/validation__magnifier-tick-dist-endpoints-01.pine +0 -0
  183. {pineforge_codegen-0.7.2 → pineforge_codegen-0.7.4}/tests/gate-corpus/ok/validation__magnifier-tick-dist-endpoints-rsi-cross-08a.pine +0 -0
  184. {pineforge_codegen-0.7.2 → pineforge_codegen-0.7.4}/tests/gate-corpus/ok/validation__magnifier-tick-dist-volume-weighted-on-01.pine +0 -0
  185. {pineforge_codegen-0.7.2 → pineforge_codegen-0.7.4}/tests/gate-corpus/ok/validation__matrix-bool-mask-explicit-utc-tz-01.pine +0 -0
  186. {pineforge_codegen-0.7.2 → pineforge_codegen-0.7.4}/tests/gate-corpus/ok/validation__matrix-bool-mask-no-transpose-01.pine +0 -0
  187. {pineforge_codegen-0.7.2 → pineforge_codegen-0.7.4}/tests/gate-corpus/ok/validation__matrix-bool-mask-transpose-roundtrip-01.pine +0 -0
  188. {pineforge_codegen-0.7.2 → pineforge_codegen-0.7.4}/tests/gate-corpus/ok/validation__matrix-bool-regime-mask-24x7-01.pine +0 -0
  189. {pineforge_codegen-0.7.2 → pineforge_codegen-0.7.4}/tests/gate-corpus/ok/validation__matrix-covariance-eigen-pca-01.pine +0 -0
  190. {pineforge_codegen-0.7.2 → pineforge_codegen-0.7.4}/tests/gate-corpus/ok/validation__matrix-eigen-rank-deficient-cov-01.pine +0 -0
  191. {pineforge_codegen-0.7.2 → pineforge_codegen-0.7.4}/tests/gate-corpus/ok/validation__mtf-daily-array-median-percentrank-01.pine +0 -0
  192. {pineforge_codegen-0.7.2 → pineforge_codegen-0.7.4}/tests/gate-corpus/ok/validation__mtf-daily-ema26-warmup-01.pine +0 -0
  193. {pineforge_codegen-0.7.2 → pineforge_codegen-0.7.4}/tests/gate-corpus/ok/validation__mtf-daily-prev-high-break-01.pine +0 -0
  194. {pineforge_codegen-0.7.2 → pineforge_codegen-0.7.4}/tests/gate-corpus/ok/validation__mtf-dual-tf-60-240-rising-01.pine +0 -0
  195. {pineforge_codegen-0.7.2 → pineforge_codegen-0.7.4}/tests/gate-corpus/ok/validation__mtf-htf-60-close-change-baseline-01.pine +0 -0
  196. {pineforge_codegen-0.7.2 → pineforge_codegen-0.7.4}/tests/gate-corpus/ok/validation__mtf-htf-60-close-roll-01.pine +0 -0
  197. {pineforge_codegen-0.7.2 → pineforge_codegen-0.7.4}/tests/gate-corpus/ok/validation__mtf-htf-60-gaps-on-roll-01.pine +0 -0
  198. {pineforge_codegen-0.7.2 → pineforge_codegen-0.7.4}/tests/gate-corpus/ok/validation__mtf-htf-60-rsi14-inside-security-01.pine +0 -0
  199. {pineforge_codegen-0.7.2 → pineforge_codegen-0.7.4}/tests/gate-corpus/ok/validation__mtf-htf-60-sma20-inside-security-01.pine +0 -0
  200. {pineforge_codegen-0.7.2 → pineforge_codegen-0.7.4}/tests/gate-corpus/ok/validation__mtf-htf-60-volume-spike-01.pine +0 -0
  201. {pineforge_codegen-0.7.2 → pineforge_codegen-0.7.4}/tests/gate-corpus/ok/validation__mtf-htf-confluence-manual-trail-01.pine +0 -0
  202. {pineforge_codegen-0.7.2 → pineforge_codegen-0.7.4}/tests/gate-corpus/ok/validation__mtf-htf-confluence-static-bracket-01.pine +0 -0
  203. {pineforge_codegen-0.7.2 → pineforge_codegen-0.7.4}/tests/gate-corpus/ok/validation__mtf-htf-weekly-sma-cross-01.pine +0 -0
  204. {pineforge_codegen-0.7.2 → pineforge_codegen-0.7.4}/tests/gate-corpus/ok/validation__mtf-roll-state-60-240-d-minimal-01.pine +0 -0
  205. {pineforge_codegen-0.7.2 → pineforge_codegen-0.7.4}/tests/gate-corpus/ok/validation__mtf-triple-tf-close-confluence-01.pine +0 -0
  206. {pineforge_codegen-0.7.2 → pineforge_codegen-0.7.4}/tests/gate-corpus/ok/validation__mtf-triple-tf-macd-hist-confluence-01.pine +0 -0
  207. {pineforge_codegen-0.7.2 → pineforge_codegen-0.7.4}/tests/gate-corpus/ok/validation__na-deep-history-int-na-01.pine +0 -0
  208. {pineforge_codegen-0.7.2 → pineforge_codegen-0.7.4}/tests/gate-corpus/ok/validation__na-nz-fixnan-history-chain-01.pine +0 -0
  209. {pineforge_codegen-0.7.2 → pineforge_codegen-0.7.4}/tests/gate-corpus/ok/validation__oca-exit-bracket-internal-cancel-01.pine +0 -0
  210. {pineforge_codegen-0.7.2 → pineforge_codegen-0.7.4}/tests/gate-corpus/ok/validation__oca-multi-bracket-isolation-01.pine +0 -0
  211. {pineforge_codegen-0.7.2 → pineforge_codegen-0.7.4}/tests/gate-corpus/ok/validation__oca-raw-strategy-order-reduce-01.pine +0 -0
  212. {pineforge_codegen-0.7.2 → pineforge_codegen-0.7.4}/tests/gate-corpus/ok/validation__order-close-all-cancel-all-01.pine +0 -0
  213. {pineforge_codegen-0.7.2 → pineforge_codegen-0.7.4}/tests/gate-corpus/ok/validation__order-close-immediate-vs-next-bar-01.pine +0 -0
  214. {pineforge_codegen-0.7.2 → pineforge_codegen-0.7.4}/tests/gate-corpus/ok/validation__order-cross-entry-cancel-same-pass-01.pine +0 -0
  215. {pineforge_codegen-0.7.2 → pineforge_codegen-0.7.4}/tests/gate-corpus/ok/validation__order-cross-entry-close-same-pass-01.pine +0 -0
  216. {pineforge_codegen-0.7.2 → pineforge_codegen-0.7.4}/tests/gate-corpus/ok/validation__order-cross-exit-close-same-pass-01.pine +0 -0
  217. {pineforge_codegen-0.7.2 → pineforge_codegen-0.7.4}/tests/gate-corpus/ok/validation__order-deferred-flip-guaranteed-gap-stops-01.pine +0 -0
  218. {pineforge_codegen-0.7.2 → pineforge_codegen-0.7.4}/tests/gate-corpus/ok/validation__order-deferred-flip-pooc-cross-bar-01.pine +0 -0
  219. {pineforge_codegen-0.7.2 → pineforge_codegen-0.7.4}/tests/gate-corpus/ok/validation__order-dual-four-bar-stop-no-close-01.pine +0 -0
  220. {pineforge_codegen-0.7.2 → pineforge_codegen-0.7.4}/tests/gate-corpus/ok/validation__order-dual-side-same-id-stop-no-cancel-01.pine +0 -0
  221. {pineforge_codegen-0.7.2 → pineforge_codegen-0.7.4}/tests/gate-corpus/ok/validation__order-dual-stop-both-touch-priority-01.pine +0 -0
  222. {pineforge_codegen-0.7.2 → pineforge_codegen-0.7.4}/tests/gate-corpus/ok/validation__order-dual-stop-cancel-rotation-01.pine +0 -0
  223. {pineforge_codegen-0.7.2 → pineforge_codegen-0.7.4}/tests/gate-corpus/ok/validation__order-dual-stop-far-only-01.pine +0 -0
  224. {pineforge_codegen-0.7.2 → pineforge_codegen-0.7.4}/tests/gate-corpus/ok/validation__order-dual-stop-near-only-01.pine +0 -0
  225. {pineforge_codegen-0.7.2 → pineforge_codegen-0.7.4}/tests/gate-corpus/ok/validation__order-dual-stop-open-high-first-path-01.pine +0 -0
  226. {pineforge_codegen-0.7.2 → pineforge_codegen-0.7.4}/tests/gate-corpus/ok/validation__order-dual-stop-open-low-first-path-01.pine +0 -0
  227. {pineforge_codegen-0.7.2 → pineforge_codegen-0.7.4}/tests/gate-corpus/ok/validation__order-dual-stop-open-tie-01.pine +0 -0
  228. {pineforge_codegen-0.7.2 → pineforge_codegen-0.7.4}/tests/gate-corpus/ok/validation__order-dual-stop-source-order-long-first-01.pine +0 -0
  229. {pineforge_codegen-0.7.2 → pineforge_codegen-0.7.4}/tests/gate-corpus/ok/validation__order-dual-stop-source-order-short-first-01.pine +0 -0
  230. {pineforge_codegen-0.7.2 → pineforge_codegen-0.7.4}/tests/gate-corpus/ok/validation__order-entry-implicit-reversal-exit-01.pine +0 -0
  231. {pineforge_codegen-0.7.2 → pineforge_codegen-0.7.4}/tests/gate-corpus/ok/validation__order-flip-stop-no-paired-close-01.pine +0 -0
  232. {pineforge_codegen-0.7.2 → pineforge_codegen-0.7.4}/tests/gate-corpus/ok/validation__order-market-close-fill-basis-01.pine +0 -0
  233. {pineforge_codegen-0.7.2 → pineforge_codegen-0.7.4}/tests/gate-corpus/ok/validation__order-one-side-four-bar-far-opposite-01.pine +0 -0
  234. {pineforge_codegen-0.7.2 → pineforge_codegen-0.7.4}/tests/gate-corpus/ok/validation__order-opposite-entry-close-same-pass-01.pine +0 -0
  235. {pineforge_codegen-0.7.2 → pineforge_codegen-0.7.4}/tests/gate-corpus/ok/validation__order-percent-equity-cash-commission-01.pine +0 -0
  236. {pineforge_codegen-0.7.2 → pineforge_codegen-0.7.4}/tests/gate-corpus/ok/validation__order-process-on-close-false-01.pine +0 -0
  237. {pineforge_codegen-0.7.2 → pineforge_codegen-0.7.4}/tests/gate-corpus/ok/validation__order-process-on-close-true-01.pine +0 -0
  238. {pineforge_codegen-0.7.2 → pineforge_codegen-0.7.4}/tests/gate-corpus/ok/validation__order-range-expansion-pending-stop-01.pine +0 -0
  239. {pineforge_codegen-0.7.2 → pineforge_codegen-0.7.4}/tests/gate-corpus/ok/validation__order-same-id-entry-close-same-bar-01.pine +0 -0
  240. {pineforge_codegen-0.7.2 → pineforge_codegen-0.7.4}/tests/gate-corpus/ok/validation__order-same-id-market-entry-repeat-01.pine +0 -0
  241. {pineforge_codegen-0.7.2 → pineforge_codegen-0.7.4}/tests/gate-corpus/ok/validation__order-same-id-stop-after-flat-01.pine +0 -0
  242. {pineforge_codegen-0.7.2 → pineforge_codegen-0.7.4}/tests/gate-corpus/ok/validation__order-same-id-stop-cross-before-modify-01.pine +0 -0
  243. {pineforge_codegen-0.7.2 → pineforge_codegen-0.7.4}/tests/gate-corpus/ok/validation__order-same-id-stop-minute-zero-01.pine +0 -0
  244. {pineforge_codegen-0.7.2 → pineforge_codegen-0.7.4}/tests/gate-corpus/ok/validation__order-same-id-stop-modification-01.pine +0 -0
  245. {pineforge_codegen-0.7.2 → pineforge_codegen-0.7.4}/tests/gate-corpus/ok/validation__order-same-id-stop-raise-only-01.pine +0 -0
  246. {pineforge_codegen-0.7.2 → pineforge_codegen-0.7.4}/tests/gate-corpus/ok/validation__order-same-id-stop-window-four-bars-01.pine +0 -0
  247. {pineforge_codegen-0.7.2 → pineforge_codegen-0.7.4}/tests/gate-corpus/ok/validation__order-stale-stop-after-close-no-cancel-01.pine +0 -0
  248. {pineforge_codegen-0.7.2 → pineforge_codegen-0.7.4}/tests/gate-corpus/ok/validation__order-stop-cancel-no-regime-close-01.pine +0 -0
  249. {pineforge_codegen-0.7.2 → pineforge_codegen-0.7.4}/tests/gate-corpus/ok/validation__order-stop-entry-cancel-opposite-01.pine +0 -0
  250. {pineforge_codegen-0.7.2 → pineforge_codegen-0.7.4}/tests/gate-corpus/ok/validation__order-stop-entry-reversal-grouping-01.pine +0 -0
  251. {pineforge_codegen-0.7.2 → pineforge_codegen-0.7.4}/tests/gate-corpus/ok/validation__order-stop-entry-touch-boundary-01.pine +0 -0
  252. {pineforge_codegen-0.7.2 → pineforge_codegen-0.7.4}/tests/gate-corpus/ok/validation__pyramid-cash-fractional-commission-01.pine +0 -0
  253. {pineforge_codegen-0.7.2 → pineforge_codegen-0.7.4}/tests/gate-corpus/ok/validation__pyramid-close-id-grouping-01.pine +0 -0
  254. {pineforge_codegen-0.7.2 → pineforge_codegen-0.7.4}/tests/gate-corpus/ok/validation__pyramid-deferred-flip-close-all-01.pine +0 -0
  255. {pineforge_codegen-0.7.2 → pineforge_codegen-0.7.4}/tests/gate-corpus/ok/validation__pyramid-flip-stop-pyramiding-2-01.pine +0 -0
  256. {pineforge_codegen-0.7.2 → pineforge_codegen-0.7.4}/tests/gate-corpus/ok/validation__recompute-alma-sar-corr-magnifier-01.pine +0 -0
  257. {pineforge_codegen-0.7.2 → pineforge_codegen-0.7.4}/tests/gate-corpus/ok/validation__recompute-mtf-rsi-macd-bb-01.pine +0 -0
  258. {pineforge_codegen-0.7.2 → pineforge_codegen-0.7.4}/tests/gate-corpus/ok/validation__risk-max-contracts-held-gate-pyramid-01.pine +0 -0
  259. {pineforge_codegen-0.7.2 → pineforge_codegen-0.7.4}/tests/gate-corpus/ok/validation__session-hour-minute-pulse-filter-01.pine +0 -0
  260. {pineforge_codegen-0.7.2 → pineforge_codegen-0.7.4}/tests/gate-corpus/ok/validation__session-ny-spring-forward-dst-01.pine +0 -0
  261. {pineforge_codegen-0.7.2 → pineforge_codegen-0.7.4}/tests/gate-corpus/ok/validation__stats-eventrades-zero-pnl-count-01.pine +0 -0
  262. {pineforge_codegen-0.7.2 → pineforge_codegen-0.7.4}/tests/gate-corpus/ok/validation__ta-accdist-ema-cross-01.pine +0 -0
  263. {pineforge_codegen-0.7.2 → pineforge_codegen-0.7.4}/tests/gate-corpus/ok/validation__ta-bb-kc-squeeze-breakout-01.pine +0 -0
  264. {pineforge_codegen-0.7.2 → pineforge_codegen-0.7.4}/tests/gate-corpus/ok/validation__ta-bb-rsi-mean-reversion-01.pine +0 -0
  265. {pineforge_codegen-0.7.2 → pineforge_codegen-0.7.4}/tests/gate-corpus/ok/validation__ta-cci-threshold-cross-01.pine +0 -0
  266. {pineforge_codegen-0.7.2 → pineforge_codegen-0.7.4}/tests/gate-corpus/ok/validation__ta-chandelier-exit-direction-01.pine +0 -0
  267. {pineforge_codegen-0.7.2 → pineforge_codegen-0.7.4}/tests/gate-corpus/ok/validation__ta-closedtrades-risk-introspection-01.pine +0 -0
  268. {pineforge_codegen-0.7.2 → pineforge_codegen-0.7.4}/tests/gate-corpus/ok/validation__ta-cmo-9-zero-cross-01.pine +0 -0
  269. {pineforge_codegen-0.7.2 → pineforge_codegen-0.7.4}/tests/gate-corpus/ok/validation__ta-cog-10-signal-cross-01.pine +0 -0
  270. {pineforge_codegen-0.7.2 → pineforge_codegen-0.7.4}/tests/gate-corpus/ok/validation__ta-dmi-adx-di-cross-01.pine +0 -0
  271. {pineforge_codegen-0.7.2 → pineforge_codegen-0.7.4}/tests/gate-corpus/ok/validation__ta-donchian-channel-breakout-01.pine +0 -0
  272. {pineforge_codegen-0.7.2 → pineforge_codegen-0.7.4}/tests/gate-corpus/ok/validation__ta-dual-ma-switch-dispatch-01.pine +0 -0
  273. {pineforge_codegen-0.7.2 → pineforge_codegen-0.7.4}/tests/gate-corpus/ok/validation__ta-dual-thrust-open-anchored-range-01.pine +0 -0
  274. {pineforge_codegen-0.7.2 → pineforge_codegen-0.7.4}/tests/gate-corpus/ok/validation__ta-elder-ray-bull-bear-power-01.pine +0 -0
  275. {pineforge_codegen-0.7.2 → pineforge_codegen-0.7.4}/tests/gate-corpus/ok/validation__ta-ema-ribbon-stack-transition-01.pine +0 -0
  276. {pineforge_codegen-0.7.2 → pineforge_codegen-0.7.4}/tests/gate-corpus/ok/validation__ta-engulfing-candle-pattern-01.pine +0 -0
  277. {pineforge_codegen-0.7.2 → pineforge_codegen-0.7.4}/tests/gate-corpus/ok/validation__ta-highestbars-lowestbars-breakout-01.pine +0 -0
  278. {pineforge_codegen-0.7.2 → pineforge_codegen-0.7.4}/tests/gate-corpus/ok/validation__ta-hma-55-close-cross-01.pine +0 -0
  279. {pineforge_codegen-0.7.2 → pineforge_codegen-0.7.4}/tests/gate-corpus/ok/validation__ta-hma-fast-slow-cross-01.pine +0 -0
  280. {pineforge_codegen-0.7.2 → pineforge_codegen-0.7.4}/tests/gate-corpus/ok/validation__ta-inside-bar-engulfing-01.pine +0 -0
  281. {pineforge_codegen-0.7.2 → pineforge_codegen-0.7.4}/tests/gate-corpus/ok/validation__ta-kama-style-efficiency-ratio-01.pine +0 -0
  282. {pineforge_codegen-0.7.2 → pineforge_codegen-0.7.4}/tests/gate-corpus/ok/validation__ta-keltner-channel-break-01.pine +0 -0
  283. {pineforge_codegen-0.7.2 → pineforge_codegen-0.7.4}/tests/gate-corpus/ok/validation__ta-linreg-stdev-channel-revert-01.pine +0 -0
  284. {pineforge_codegen-0.7.2 → pineforge_codegen-0.7.4}/tests/gate-corpus/ok/validation__ta-macd-12-26-9-line-signal-cross-01.pine +0 -0
  285. {pineforge_codegen-0.7.2 → pineforge_codegen-0.7.4}/tests/gate-corpus/ok/validation__ta-macd-histogram-reversal-01.pine +0 -0
  286. {pineforge_codegen-0.7.2 → pineforge_codegen-0.7.4}/tests/gate-corpus/ok/validation__ta-macd-line-gt-signal-continuous-state-01.pine +0 -0
  287. {pineforge_codegen-0.7.2 → pineforge_codegen-0.7.4}/tests/gate-corpus/ok/validation__ta-map-regime-threshold-lookup-01.pine +0 -0
  288. {pineforge_codegen-0.7.2 → pineforge_codegen-0.7.4}/tests/gate-corpus/ok/validation__ta-median-vs-ema-cross-01.pine +0 -0
  289. {pineforge_codegen-0.7.2 → pineforge_codegen-0.7.4}/tests/gate-corpus/ok/validation__ta-mfi-14-bands-20-80-01.pine +0 -0
  290. {pineforge_codegen-0.7.2 → pineforge_codegen-0.7.4}/tests/gate-corpus/ok/validation__ta-momentum-roc-zero-cross-01.pine +0 -0
  291. {pineforge_codegen-0.7.2 → pineforge_codegen-0.7.4}/tests/gate-corpus/ok/validation__ta-multi-indicator-score-composite-01.pine +0 -0
  292. {pineforge_codegen-0.7.2 → pineforge_codegen-0.7.4}/tests/gate-corpus/ok/validation__ta-nvi-pvi-cross-01.pine +0 -0
  293. {pineforge_codegen-0.7.2 → pineforge_codegen-0.7.4}/tests/gate-corpus/ok/validation__ta-obv-ema-cross-01.pine +0 -0
  294. {pineforge_codegen-0.7.2 → pineforge_codegen-0.7.4}/tests/gate-corpus/ok/validation__ta-percentrank-mean-reversion-01.pine +0 -0
  295. {pineforge_codegen-0.7.2 → pineforge_codegen-0.7.4}/tests/gate-corpus/ok/validation__ta-pivot-array-unshift-pop-01.pine +0 -0
  296. {pineforge_codegen-0.7.2 → pineforge_codegen-0.7.4}/tests/gate-corpus/ok/validation__ta-pivot-atr-stop-target-01.pine +0 -0
  297. {pineforge_codegen-0.7.2 → pineforge_codegen-0.7.4}/tests/gate-corpus/ok/validation__ta-pivot-confirmed-break-01.pine +0 -0
  298. {pineforge_codegen-0.7.2 → pineforge_codegen-0.7.4}/tests/gate-corpus/ok/validation__ta-pivot-point-levels-break-01.pine +0 -0
  299. {pineforge_codegen-0.7.2 → pineforge_codegen-0.7.4}/tests/gate-corpus/ok/validation__ta-pvt-ema-cross-01.pine +0 -0
  300. {pineforge_codegen-0.7.2 → pineforge_codegen-0.7.4}/tests/gate-corpus/ok/validation__ta-range-filter-var-band-01.pine +0 -0
  301. {pineforge_codegen-0.7.2 → pineforge_codegen-0.7.4}/tests/gate-corpus/ok/validation__ta-rci-14-zero-cross-01.pine +0 -0
  302. {pineforge_codegen-0.7.2 → pineforge_codegen-0.7.4}/tests/gate-corpus/ok/validation__ta-rsi-bb-self-bands-01.pine +0 -0
  303. {pineforge_codegen-0.7.2 → pineforge_codegen-0.7.4}/tests/gate-corpus/ok/validation__ta-rsi-ema-signal-cross-01.pine +0 -0
  304. {pineforge_codegen-0.7.2 → pineforge_codegen-0.7.4}/tests/gate-corpus/ok/validation__ta-rsi-macd-and-continuous-state-01.pine +0 -0
  305. {pineforge_codegen-0.7.2 → pineforge_codegen-0.7.4}/tests/gate-corpus/ok/validation__ta-rsi14-bands-30-70-01.pine +0 -0
  306. {pineforge_codegen-0.7.2 → pineforge_codegen-0.7.4}/tests/gate-corpus/ok/validation__ta-rsi14-cross-50-01.pine +0 -0
  307. {pineforge_codegen-0.7.2 → pineforge_codegen-0.7.4}/tests/gate-corpus/ok/validation__ta-rsi14-gt-50-continuous-state-01.pine +0 -0
  308. {pineforge_codegen-0.7.2 → pineforge_codegen-0.7.4}/tests/gate-corpus/ok/validation__ta-rsi14-gt60-lt45-no-matrix-01.pine +0 -0
  309. {pineforge_codegen-0.7.2 → pineforge_codegen-0.7.4}/tests/gate-corpus/ok/validation__ta-sar-flip-entry-01.pine +0 -0
  310. {pineforge_codegen-0.7.2 → pineforge_codegen-0.7.4}/tests/gate-corpus/ok/validation__ta-sma-152-close-cross-01.pine +0 -0
  311. {pineforge_codegen-0.7.2 → pineforge_codegen-0.7.4}/tests/gate-corpus/ok/validation__ta-sma-dual-cross-01.pine +0 -0
  312. {pineforge_codegen-0.7.2 → pineforge_codegen-0.7.4}/tests/gate-corpus/ok/validation__ta-stdev-sma-expansion-break-01.pine +0 -0
  313. {pineforge_codegen-0.7.2 → pineforge_codegen-0.7.4}/tests/gate-corpus/ok/validation__ta-stoch-slow-k-d-cross-01.pine +0 -0
  314. {pineforge_codegen-0.7.2 → pineforge_codegen-0.7.4}/tests/gate-corpus/ok/validation__ta-stochastic-rsi-cross-01.pine +0 -0
  315. {pineforge_codegen-0.7.2 → pineforge_codegen-0.7.4}/tests/gate-corpus/ok/validation__ta-str-match-regex-filter-01.pine +0 -0
  316. {pineforge_codegen-0.7.2 → pineforge_codegen-0.7.4}/tests/gate-corpus/ok/validation__ta-supertrend-adx-filter-01.pine +0 -0
  317. {pineforge_codegen-0.7.2 → pineforge_codegen-0.7.4}/tests/gate-corpus/ok/validation__ta-supertrend-direction-flip-01.pine +0 -0
  318. {pineforge_codegen-0.7.2 → pineforge_codegen-0.7.4}/tests/gate-corpus/ok/validation__ta-triple-sma-stack-latch-01.pine +0 -0
  319. {pineforge_codegen-0.7.2 → pineforge_codegen-0.7.4}/tests/gate-corpus/ok/validation__ta-tsi-25-13-signal-cross-01.pine +0 -0
  320. {pineforge_codegen-0.7.2 → pineforge_codegen-0.7.4}/tests/gate-corpus/ok/validation__ta-volume-spike-atr-breakout-01.pine +0 -0
  321. {pineforge_codegen-0.7.2 → pineforge_codegen-0.7.4}/tests/gate-corpus/ok/validation__ta-vwma-vs-sma-divergence-01.pine +0 -0
  322. {pineforge_codegen-0.7.2 → pineforge_codegen-0.7.4}/tests/gate-corpus/ok/validation__ta-wpr-14-bands-01.pine +0 -0
  323. {pineforge_codegen-0.7.2 → pineforge_codegen-0.7.4}/tests/gate-corpus/ok/validation__timeframe-main-period-self-adaptive-01.pine +0 -0
  324. {pineforge_codegen-0.7.2 → pineforge_codegen-0.7.4}/tests/gate-corpus/ok/validation__udt-method-calls-sibling-cumulative-01.pine +0 -0
  325. {pineforge_codegen-0.7.2 → pineforge_codegen-0.7.4}/tests/gate-corpus/ok/validation__udt-method-default-param-kwargs-01.pine +0 -0
  326. {pineforge_codegen-0.7.2 → pineforge_codegen-0.7.4}/tests/gate-corpus/ok/validation__udt-method-drives-strategy-entry-01.pine +0 -0
  327. {pineforge_codegen-0.7.2 → pineforge_codegen-0.7.4}/tests/gate-corpus/ok/validation__udt-method-extra-primitive-args-01.pine +0 -0
  328. {pineforge_codegen-0.7.2 → pineforge_codegen-0.7.4}/tests/gate-corpus/ok/validation__udt-method-feeds-strategy-exit-prices-01.pine +0 -0
  329. {pineforge_codegen-0.7.2 → pineforge_codegen-0.7.4}/tests/gate-corpus/ok/validation__udt-method-in-for-loop-01.pine +0 -0
  330. {pineforge_codegen-0.7.2 → pineforge_codegen-0.7.4}/tests/gate-corpus/ok/validation__udt-method-in-if-else-branch-01.pine +0 -0
  331. {pineforge_codegen-0.7.2 → pineforge_codegen-0.7.4}/tests/gate-corpus/ok/validation__udt-method-in-switch-arms-01.pine +0 -0
  332. {pineforge_codegen-0.7.2 → pineforge_codegen-0.7.4}/tests/gate-corpus/ok/validation__udt-method-in-while-loop-01.pine +0 -0
  333. {pineforge_codegen-0.7.2 → pineforge_codegen-0.7.4}/tests/gate-corpus/ok/validation__udt-method-mutating-self-ref-01.pine +0 -0
  334. {pineforge_codegen-0.7.2 → pineforge_codegen-0.7.4}/tests/gate-corpus/ok/validation__udt-method-on-array-element-01.pine +0 -0
  335. {pineforge_codegen-0.7.2 → pineforge_codegen-0.7.4}/tests/gate-corpus/ok/validation__udt-method-reads-strategy-state-01.pine +0 -0
  336. {pineforge_codegen-0.7.2 → pineforge_codegen-0.7.4}/tests/gate-corpus/ok/validation__udt-method-receives-ta-series-param-01.pine +0 -0
  337. {pineforge_codegen-0.7.2 → pineforge_codegen-0.7.4}/tests/gate-corpus/ok/validation__udt-method-scalar-return-01.pine +0 -0
  338. {pineforge_codegen-0.7.2 → pineforge_codegen-0.7.4}/tests/gate-corpus/ok/validation__udt-method-tuple-return-destructure-01.pine +0 -0
  339. {pineforge_codegen-0.7.2 → pineforge_codegen-0.7.4}/tests/gate-corpus/ok/validation__udt-method-udt-return-from-func-01.pine +0 -0
  340. {pineforge_codegen-0.7.2 → pineforge_codegen-0.7.4}/tests/gate-corpus/ok/validation__udt-method-uses-history-globals-01.pine +0 -0
  341. {pineforge_codegen-0.7.2 → pineforge_codegen-0.7.4}/tests/gate-corpus/ok/validation__udt-method-uses-math-funcs-01.pine +0 -0
  342. {pineforge_codegen-0.7.2 → pineforge_codegen-0.7.4}/tests/gate-corpus/ok/validation__udt-method-uses-na-nz-fixnan-01.pine +0 -0
  343. {pineforge_codegen-0.7.2 → pineforge_codegen-0.7.4}/tests/gate-corpus/ok/validation__udt-method-var-instance-streak-01.pine +0 -0
  344. {pineforge_codegen-0.7.2 → pineforge_codegen-0.7.4}/tests/gate-corpus/ok/validation__udt-method-windowed-method-chain-01.pine +0 -0
  345. {pineforge_codegen-0.7.2 → pineforge_codegen-0.7.4}/tests/gate-corpus/ok/validation__udt-regime-stack-stress-01.pine +0 -0
  346. {pineforge_codegen-0.7.2 → pineforge_codegen-0.7.4}/tests/gate-corpus/ok/validation__vwap-bands-breakout-1sigma-01.pine +0 -0
  347. {pineforge_codegen-0.7.2 → pineforge_codegen-0.7.4}/tests/gate-corpus/ok/validation__vwap-bands-mean-reversion-2sigma-01.pine +0 -0
  348. {pineforge_codegen-0.7.2 → pineforge_codegen-0.7.4}/tests/golden/matrix_eigen_pca.cpp +0 -0
  349. {pineforge_codegen-0.7.2 → pineforge_codegen-0.7.4}/tests/test_analyzer.py +0 -0
  350. {pineforge_codegen-0.7.2 → pineforge_codegen-0.7.4}/tests/test_analyzer_matrix_inference.py +0 -0
  351. {pineforge_codegen-0.7.2 → pineforge_codegen-0.7.4}/tests/test_analyzer_ta_return_types.py +0 -0
  352. {pineforge_codegen-0.7.2 → pineforge_codegen-0.7.4}/tests/test_codegen_audit_fixes.py +0 -0
  353. {pineforge_codegen-0.7.2 → pineforge_codegen-0.7.4}/tests/test_codegen_determinism.py +0 -0
  354. {pineforge_codegen-0.7.2 → pineforge_codegen-0.7.4}/tests/test_codegen_fallthrough_guards.py +0 -0
  355. {pineforge_codegen-0.7.2 → pineforge_codegen-0.7.4}/tests/test_codegen_golden.py +0 -0
  356. {pineforge_codegen-0.7.2 → pineforge_codegen-0.7.4}/tests/test_codegen_input_getters.py +0 -0
  357. {pineforge_codegen-0.7.2 → pineforge_codegen-0.7.4}/tests/test_codegen_matrix_typed.py +0 -0
  358. {pineforge_codegen-0.7.2 → pineforge_codegen-0.7.4}/tests/test_codegen_new.py +0 -0
  359. {pineforge_codegen-0.7.2 → pineforge_codegen-0.7.4}/tests/test_compile_corpus.py +0 -0
  360. {pineforge_codegen-0.7.2 → pineforge_codegen-0.7.4}/tests/test_compile_smoke.py +0 -0
  361. {pineforge_codegen-0.7.2 → pineforge_codegen-0.7.4}/tests/test_errors.py +0 -0
  362. {pineforge_codegen-0.7.2 → pineforge_codegen-0.7.4}/tests/test_import_all.py +0 -0
  363. {pineforge_codegen-0.7.2 → pineforge_codegen-0.7.4}/tests/test_input_time_int64.py +0 -0
  364. {pineforge_codegen-0.7.2 → pineforge_codegen-0.7.4}/tests/test_int64_time_storage.py +0 -0
  365. {pineforge_codegen-0.7.2 → pineforge_codegen-0.7.4}/tests/test_lexer.py +0 -0
  366. {pineforge_codegen-0.7.2 → pineforge_codegen-0.7.4}/tests/test_parser.py +0 -0
  367. {pineforge_codegen-0.7.2 → pineforge_codegen-0.7.4}/tests/test_security_tf_literal.py +0 -0
  368. {pineforge_codegen-0.7.2 → pineforge_codegen-0.7.4}/tests/test_signatures.py +0 -0
  369. {pineforge_codegen-0.7.2 → pineforge_codegen-0.7.4}/tests/test_support_checker_chart_visible_bar_time.py +0 -0
  370. {pineforge_codegen-0.7.2 → pineforge_codegen-0.7.4}/tests/test_support_checker_color_cast.py +0 -0
  371. {pineforge_codegen-0.7.2 → pineforge_codegen-0.7.4}/tests/test_support_checker_const_namespaces.py +0 -0
  372. {pineforge_codegen-0.7.2 → pineforge_codegen-0.7.4}/tests/test_support_checker_dividends_earnings.py +0 -0
  373. {pineforge_codegen-0.7.2 → pineforge_codegen-0.7.4}/tests/test_support_checker_footprint.py +0 -0
  374. {pineforge_codegen-0.7.2 → pineforge_codegen-0.7.4}/tests/test_support_checker_input_color.py +0 -0
  375. {pineforge_codegen-0.7.2 → pineforge_codegen-0.7.4}/tests/test_support_checker_input_source.py +0 -0
  376. {pineforge_codegen-0.7.2 → pineforge_codegen-0.7.4}/tests/test_support_checker_matrix.py +0 -0
  377. {pineforge_codegen-0.7.2 → pineforge_codegen-0.7.4}/tests/test_support_checker_security_adjustment.py +0 -0
  378. {pineforge_codegen-0.7.2 → pineforge_codegen-0.7.4}/tests/test_support_checker_timeframe_from_seconds.py +0 -0
  379. {pineforge_codegen-0.7.2 → pineforge_codegen-0.7.4}/tests/test_support_checker_varip.py +0 -0
  380. {pineforge_codegen-0.7.2 → pineforge_codegen-0.7.4}/tests/test_support_checker_volume_row.py +0 -0
  381. {pineforge_codegen-0.7.2 → pineforge_codegen-0.7.4}/tests/test_symbols.py +0 -0
  382. {pineforge_codegen-0.7.2 → pineforge_codegen-0.7.4}/tests/test_ta_official_surface.py +0 -0
  383. {pineforge_codegen-0.7.2 → pineforge_codegen-0.7.4}/tests/test_transpile_division.py +0 -0
  384. {pineforge_codegen-0.7.2 → pineforge_codegen-0.7.4}/tests/test_transpile_enum_order.py +0 -0
  385. {pineforge_codegen-0.7.2 → pineforge_codegen-0.7.4}/tests/test_transpile_pf_trace.py +0 -0
  386. {pineforge_codegen-0.7.2 → pineforge_codegen-0.7.4}/tests/test_transpile_tr_handle_na.py +0 -0
  387. {pineforge_codegen-0.7.2 → pineforge_codegen-0.7.4}/tests/test_transpiler_matrix_kwargs.py +0 -0
  388. {pineforge_codegen-0.7.2 → pineforge_codegen-0.7.4}/tests/test_typespec_matrix.py +0 -0
  389. {pineforge_codegen-0.7.2 → pineforge_codegen-0.7.4}/tests/test_udt_drawing_field_cleanup.py +0 -0
  390. {pineforge_codegen-0.7.2 → pineforge_codegen-0.7.4}/tests/test_unsupported_reporting.py +0 -0
  391. {pineforge_codegen-0.7.2 → pineforge_codegen-0.7.4}/tests/test_vwap_tuple_unpack.py +0 -0
@@ -0,0 +1,20 @@
1
+ version: 2
2
+ updates:
3
+ # Keep the SHA-pinned GitHub Actions in workflows up to date with
4
+ # reviewable PRs (security review: pinned actions need a bump path).
5
+ - package-ecosystem: "github-actions"
6
+ directory: "/"
7
+ schedule:
8
+ interval: "weekly"
9
+ # The conformance-gate / npm-package tooling (pyodide pinned to PYODIDE_TARGET,
10
+ # tar caret range) — get reviewable bump PRs. NOTE: a pyodide bump must move
11
+ # PYODIDE_TARGET in lockstep (the gate validates against it), so review these.
12
+ - package-ecosystem: "npm"
13
+ directory: "/"
14
+ schedule:
15
+ interval: "weekly"
16
+ # Python dev deps (pytest).
17
+ - package-ecosystem: "pip"
18
+ directory: "/"
19
+ schedule:
20
+ interval: "weekly"
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: pineforge-codegen
3
- Version: 0.7.2
3
+ Version: 0.7.4
4
4
  Summary: PineScript v6 to C++ transpiler that targets the pineforge-engine runtime.
5
5
  Project-URL: Homepage, https://github.com/pineforge-4pass/pineforge-codegen-oss
6
6
  Project-URL: Issues, https://github.com/pineforge-4pass/pineforge-codegen-oss/issues
@@ -0,0 +1 @@
1
+ 0.7.4
@@ -9,13 +9,13 @@ import sys
9
9
  if "/codegen" not in sys.path:
10
10
  sys.path.insert(0, "/codegen")
11
11
 
12
- from pineforge_codegen import transpile
12
+ from pineforge_codegen import transpile_full
13
13
  from pineforge_codegen.errors import CompileError
14
14
 
15
15
 
16
16
  def transpile_json(source: str) -> str:
17
17
  try:
18
- cpp = transpile(source)
18
+ full = transpile_full(source)
19
19
  except CompileError as e:
20
20
  diags = []
21
21
  for d in e.diagnostics:
@@ -32,4 +32,4 @@ def transpile_json(source: str) -> str:
32
32
  entry["endCol"] = end_col
33
33
  diags.append(entry)
34
34
  return json.dumps({"ok": False, "error": str(e), "diagnostics": diags})
35
- return json.dumps({"ok": True, "cpp": cpp})
35
+ return json.dumps({"ok": True, "cpp": full["cpp"], "inputs": full["inputs"], "strategyParams": full["strategyParams"]})
@@ -51,3 +51,42 @@ def transpile(pine_source: str, *, check_support: bool = True, filename: str = "
51
51
  # ``if (trace_enabled_) { trace(...); ... }`` block.
52
52
  ctx.pf_trace_pragmas = pragmas
53
53
  return CodeGen(ctx).generate()
54
+
55
+
56
+ def transpile_full(pine_source: str, *, check_support: bool = True,
57
+ filename: str = "<input>") -> dict:
58
+ """Transpile like :func:`transpile`, plus the host-UI input manifest.
59
+
60
+ Runs ONE pipeline pass (Lexer -> Parser -> support check -> Analyzer ->
61
+ CodeGen.generate) and returns the generated C++ alongside the data the
62
+ cloud Studio needs to auto-build a backtest "override params" form:
63
+
64
+ - ``cpp``: the generated C++ source (identical to :func:`transpile`).
65
+ - ``inputs``: a list of ``InputDef`` dicts (one per top-level
66
+ ``var = input.*(...)`` declaration). Each has ``title`` / ``type`` /
67
+ ``default`` and optionally ``min`` / ``max`` / ``step`` / ``options``
68
+ (omitted when the corresponding signature argument is absent or
69
+ references a non-const value). See
70
+ :meth:`CodeGen.extract_input_manifest`.
71
+ - ``strategyParams``: the literal ``strategy(...)`` kwargs the analyzer
72
+ surfaced (e.g. ``initial_capital``, ``pyramiding``).
73
+
74
+ Args mirror :func:`transpile`.
75
+
76
+ Returns:
77
+ ``{"cpp": str, "inputs": list[dict], "strategyParams": dict}``.
78
+ """
79
+ pragmas = extract_pf_trace_pragmas(pine_source)
80
+ tokens = Lexer(pine_source, filename=filename).tokenize()
81
+ ast = Parser(tokens, source=pine_source, filename=filename).parse()
82
+ if check_support:
83
+ check_support_or_raise(ast, filename=filename)
84
+ ctx = Analyzer(ast, filename=filename).analyze()
85
+ ctx.pf_trace_pragmas = pragmas
86
+ gen = CodeGen(ctx)
87
+ cpp = gen.generate()
88
+ return {
89
+ "cpp": cpp,
90
+ "inputs": gen.extract_input_manifest(),
91
+ "strategyParams": dict(ctx.strategy_params),
92
+ }
@@ -469,6 +469,79 @@ class CodeGen(CallVisitor, ExprVisitor, StmtVisitor, TopLevelEmitter, SecurityEm
469
469
  self._register_global_aggregate_member_types()
470
470
  self._uses_matrix = self._detect_matrix_usage()
471
471
 
472
+ # max_bars_back: the per-variable history depth the engine's Series<T>
473
+ # ring buffer should retain. Pine exposes this two ways — the
474
+ # ``strategy(..., max_bars_back=N)`` kwarg (global) and the
475
+ # ``max_bars_back(var, N)`` function (per-var). The engine's
476
+ # ``Series<T>(int max_len)`` ctor (default 500, include/pineforge/
477
+ # series.hpp) is the wiring point: reads past the retained depth return
478
+ # na, so honoring the directive means constructing each Series with a
479
+ # capacity >= the requested depth. We take the MAX requested N and apply
480
+ # it (via ``_series_decl_suffix`` -> ``{N}``) to the directly-declared
481
+ # ``Series<T>`` members — a safe superset of Pine's per-var semantics
482
+ # (it never retains LESS than Pine, so any history access that succeeds
483
+ # in Pine succeeds here). ``None`` => no directive => keep the engine
484
+ # default 500 (emit a bare ``Series<T>`` with no ctor arg, so
485
+ # directive-free output is byte-identical to before).
486
+ #
487
+ # KNOWN LIMITATION: the lazily-constructed security-helper map series
488
+ # (``_security_helper_series_``, the ``std::unordered_map<std::string,
489
+ # Series<double>>`` ~line 971) do NOT pick up the cap. Their entries are
490
+ # default-constructed on first ``operator[]`` access, so they always use
491
+ # the engine default 500 regardless of the requested ``N``. A
492
+ # max_bars_back directive larger than 500 is therefore not honored for
493
+ # history reads off security-helper series.
494
+ self._max_bars_back_cap: int | None = self._compute_max_bars_back_cap()
495
+
496
+ @staticmethod
497
+ def _int_literal_value(node: ASTNode | None) -> int | None:
498
+ """Return the integer value of a (possibly unary-minus) NumberLiteral,
499
+ or None if ``node`` is not an integer literal expression."""
500
+ if isinstance(node, UnaryOp) and node.op == "-":
501
+ inner = CodeGen._int_literal_value(node.operand)
502
+ return -inner if inner is not None else None
503
+ if isinstance(node, NumberLiteral) and isinstance(node.value, int):
504
+ return node.value
505
+ if isinstance(node, NumberLiteral) and isinstance(node.value, float):
506
+ # Pine accepts ``max_bars_back=5e2`` style; accept integral floats.
507
+ return int(node.value) if node.value.is_integer() else None
508
+ return None
509
+
510
+ def _compute_max_bars_back_cap(self) -> int | None:
511
+ """Scan the AST for max_bars_back directives (strategy() kwarg AND the
512
+ bare function call) and return the largest positive integer requested,
513
+ or None if none is present / none is a usable literal."""
514
+ ast = getattr(self.ctx, "ast", None)
515
+ if ast is None:
516
+ return None
517
+ caps: list[int] = []
518
+ for node in self._walk_ast(ast):
519
+ if isinstance(node, StrategyDecl):
520
+ val = self._int_literal_value(node.kwargs.get("max_bars_back"))
521
+ if val is not None and val > 0:
522
+ caps.append(val)
523
+ elif (
524
+ isinstance(node, FuncCall)
525
+ and isinstance(node.callee, Identifier)
526
+ and node.callee.name == "max_bars_back"
527
+ ):
528
+ # max_bars_back(var, num) — second positional arg, or the
529
+ # ``num=`` kwarg, is the depth.
530
+ num_node = None
531
+ if len(node.args) >= 2:
532
+ num_node = node.args[1]
533
+ elif "num" in node.kwargs:
534
+ num_node = node.kwargs["num"]
535
+ val = self._int_literal_value(num_node)
536
+ if val is not None and val > 0:
537
+ caps.append(val)
538
+ return max(caps) if caps else None
539
+
540
+ def _series_decl_suffix(self) -> str:
541
+ """C++ constructor-arg suffix for Series<T> member declarations. Empty
542
+ (engine default 500) unless a max_bars_back directive raised the cap."""
543
+ return f"{{{self._max_bars_back_cap}}}" if self._max_bars_back_cap else ""
544
+
472
545
  def _register_global_aggregate_member_types(self) -> None:
473
546
  """Infer matrix/array/map class members for global non-var declarations from RHS AST.
474
547
 
@@ -802,6 +875,10 @@ class CodeGen(CallVisitor, ExprVisitor, StmtVisitor, TopLevelEmitter, SecurityEm
802
875
 
803
876
  lines: list[str] = []
804
877
 
878
+ # Series<T> ctor-arg suffix from any max_bars_back directive (empty when
879
+ # absent, so directive-free output is byte-identical to before).
880
+ _mbb = self._series_decl_suffix()
881
+
805
882
  # 1. Includes
806
883
  self._emit_includes(lines)
807
884
 
@@ -875,7 +952,7 @@ class CodeGen(CallVisitor, ExprVisitor, StmtVisitor, TopLevelEmitter, SecurityEm
875
952
  self._security_ohlc_hist_fields_by_sec.get(sec_id, ())
876
953
  ):
877
954
  lines.append(
878
- f" Series<double> {self._security_ohlc_hist_series_cpp(sec_id, field)};"
955
+ f" Series<double> {self._security_ohlc_hist_series_cpp(sec_id, field)}{_mbb};"
879
956
  )
880
957
  continue
881
958
  if returns_tuple and tuple_size and tuple_size > 0 and isinstance(expr_node, TupleLiteral):
@@ -896,7 +973,7 @@ class CodeGen(CallVisitor, ExprVisitor, StmtVisitor, TopLevelEmitter, SecurityEm
896
973
  lines.append(f" double _req_sec_{sec_id} = na<double>();")
897
974
  for field in sorted(self._security_ohlc_hist_fields_by_sec.get(sec_id, ())):
898
975
  lines.append(
899
- f" Series<double> {self._security_ohlc_hist_series_cpp(sec_id, field)};"
976
+ f" Series<double> {self._security_ohlc_hist_series_cpp(sec_id, field)}{_mbb};"
900
977
  )
901
978
 
902
979
  if self._security_calls:
@@ -911,7 +988,7 @@ class CodeGen(CallVisitor, ExprVisitor, StmtVisitor, TopLevelEmitter, SecurityEm
911
988
  state_name = self._security_state_name(info["sec_id"], name)
912
989
  cpp_type = self._security_cpp_type_for_mutable(name, ginfo)
913
990
  if getattr(ginfo, "is_series", False):
914
- lines.append(f" Series<{cpp_type}> {state_name};")
991
+ lines.append(f" Series<{cpp_type}> {state_name}{_mbb};")
915
992
  else:
916
993
  default = self._default_for_type(cpp_type)
917
994
  lines.append(f" {cpp_type} {state_name} = {default};")
@@ -938,7 +1015,7 @@ class CodeGen(CallVisitor, ExprVisitor, StmtVisitor, TopLevelEmitter, SecurityEm
938
1015
 
939
1016
  # 4. Series members for bar field history
940
1017
  for field_name in sorted(self.ctx.series_bar_fields):
941
- lines.append(f" Series<double> _s_{field_name};")
1018
+ lines.append(f" Series<double> _s_{field_name}{_mbb};")
942
1019
 
943
1020
  # 5. var/varip members (deduplicate by name)
944
1021
  seen_var_members: set[str] = set()
@@ -987,7 +1064,7 @@ class CodeGen(CallVisitor, ExprVisitor, StmtVisitor, TopLevelEmitter, SecurityEm
987
1064
  if cpp_type == "int" and self._is_int64_builtin_init(name):
988
1065
  cpp_type = "int64_t"
989
1066
  if name in self.ctx.series_vars:
990
- lines.append(f" Series<{cpp_type}> {safe};")
1067
+ lines.append(f" Series<{cpp_type}> {safe}{_mbb};")
991
1068
  else:
992
1069
  lines.append(f" {cpp_type} {safe};")
993
1070
 
@@ -996,7 +1073,7 @@ class CodeGen(CallVisitor, ExprVisitor, StmtVisitor, TopLevelEmitter, SecurityEm
996
1073
  if name not in self._var_names:
997
1074
  safe = self._safe_name(name)
998
1075
  cpp_type = self._series_type_for(name)
999
- lines.append(f" Series<{cpp_type}> {safe};")
1076
+ lines.append(f" Series<{cpp_type}> {safe}{_mbb};")
1000
1077
 
1001
1078
  # 7. Fixnan members
1002
1079
  for site in self.ctx.fixnan_sites:
@@ -1009,9 +1086,9 @@ class CodeGen(CallVisitor, ExprVisitor, StmtVisitor, TopLevelEmitter, SecurityEm
1009
1086
  # Determine type: int for count vars, double for float vars
1010
1087
  if member in ("closedtrades", "opentrades", "wintrades", "losstrades",
1011
1088
  "eventrades"):
1012
- lines.append(f" Series<int> {svar};")
1089
+ lines.append(f" Series<int> {svar}{_mbb};")
1013
1090
  else:
1014
- lines.append(f" Series<double> {svar};")
1091
+ lines.append(f" Series<double> {svar}{_mbb};")
1015
1092
 
1016
1093
  # 8b. Global-scope non-var declarations as class members
1017
1094
  # (so user-defined functions can reference them)
@@ -1063,7 +1140,7 @@ class CodeGen(CallVisitor, ExprVisitor, StmtVisitor, TopLevelEmitter, SecurityEm
1063
1140
  if self._safe_name(vname) == orig_safe:
1064
1141
  cpp_type = PINE_TYPE_TO_CPP.get(ptype, "double")
1065
1142
  if vname in self.ctx.series_vars:
1066
- lines.append(f" Series<{cpp_type}> {cloned_safe};")
1143
+ lines.append(f" Series<{cpp_type}> {cloned_safe}{_mbb};")
1067
1144
  elif vname in self._matrix_specs:
1068
1145
  lines.append(f" {self._type_spec_to_cpp(self._matrix_specs[vname])} {cloned_safe};")
1069
1146
  elif vname in self._array_vars:
@@ -1078,7 +1155,7 @@ class CodeGen(CallVisitor, ExprVisitor, StmtVisitor, TopLevelEmitter, SecurityEm
1078
1155
  # Non-var series var
1079
1156
  if orig_safe in [self._safe_name(n) for n in self.ctx.series_vars]:
1080
1157
  cpp_type = self._series_type_for(orig_safe)
1081
- lines.append(f" Series<{cpp_type}> {cloned_safe};")
1158
+ lines.append(f" Series<{cpp_type}> {cloned_safe}{_mbb};")
1082
1159
  else:
1083
1160
  lines.append(f" double {cloned_safe} = 0.0;")
1084
1161
 
@@ -15,13 +15,32 @@ Mixin contract — host class must provide:
15
15
 
16
16
  from __future__ import annotations
17
17
 
18
- from ..ast_nodes import FuncCall, Identifier, MemberAccess, StringLiteral
18
+ from ..ast_nodes import (
19
+ BoolLiteral,
20
+ FuncCall,
21
+ Identifier,
22
+ MemberAccess,
23
+ NumberLiteral,
24
+ StringLiteral,
25
+ VarDecl,
26
+ )
19
27
  from .. import signatures as sigs
20
28
 
21
29
 
22
30
  class InputHelper:
23
31
  """``input.*`` call analysis helpers — defaults, titles, getter dispatch, enum guard."""
24
32
 
33
+ # Maps the input function short-name -> the form-facing type tag emitted in
34
+ # the input manifest (consumed by the host UI's override form). ``price``
35
+ # is a float slider, ``time`` an int timestamp; everything string-like
36
+ # collapses to "string".
37
+ _FORM_TYPE = {
38
+ "int": "int", "float": "float", "bool": "bool", "string": "string",
39
+ "source": "source", "enum": "enum", "price": "float", "time": "int",
40
+ "color": "string", "timeframe": "string", "session": "string",
41
+ "symbol": "string", "text_area": "string",
42
+ }
43
+
25
44
  def _is_input_call(self, node: FuncCall) -> bool:
26
45
  """True if ``node`` is an ``input(...)`` or ``input.<type>(...)`` call."""
27
46
  func_name, namespace = self._resolve_callee(node.callee)
@@ -187,3 +206,125 @@ class InputHelper:
187
206
  f"{ename}.{dv.member} is not a member of enum {ename} "
188
207
  "(internal: Analyzer should reject this first)"
189
208
  )
209
+
210
+ # ------------------------------------------------------------------
211
+ # Input manifest extraction (host UI override-form source of truth)
212
+ # ------------------------------------------------------------------
213
+
214
+ def _literal_or_none(self, node):
215
+ """Return a JSON scalar for a *const* literal AST node, else None.
216
+
217
+ ``None`` signals non-const (an identifier, computed expression, …) so
218
+ callers can omit a bound/option that references a runtime value.
219
+ Enum member refs (``Dir.Up``) collapse to the ``"Dir.Up"`` string tag.
220
+ """
221
+ if isinstance(node, StringLiteral):
222
+ return node.value
223
+ # BoolLiteral must be checked before NumberLiteral: a Pine ``true`` is a
224
+ # BoolLiteral (not a NumberLiteral), but guarding the order keeps intent
225
+ # explicit and future-proof against bool/int node overlap.
226
+ if isinstance(node, BoolLiteral):
227
+ return node.value
228
+ if isinstance(node, NumberLiteral):
229
+ return node.value
230
+ # enum member ref like ``Dir.Up`` -> "Dir.Up" (string tag)
231
+ if isinstance(node, MemberAccess) and isinstance(node.object, Identifier):
232
+ return f"{node.object.name}.{node.member}"
233
+ return None
234
+
235
+ def _merged_args(self, node: FuncCall, func_name, namespace):
236
+ """Merge positional args + kwargs into signature-positional order.
237
+
238
+ Returns ``(param_names | None, merged_list)``. Mirrors the merge logic
239
+ in :meth:`_get_input_title` / :meth:`_get_input_default` so manifest
240
+ extraction reads bounds/options off the same positions codegen does.
241
+ """
242
+ if namespace == "input" and func_name in sigs.INPUT_FUNCTIONS:
243
+ names = sigs.get_param_names("input", func_name)
244
+ elif func_name == "input" and namespace is None:
245
+ names = sigs.get_param_names(None, "input")
246
+ else:
247
+ names = None
248
+ merged = list(node.args)
249
+ if names:
250
+ for i, pname in enumerate(names):
251
+ if pname in node.kwargs:
252
+ while len(merged) <= i:
253
+ merged.append(None)
254
+ if merged[i] is None:
255
+ merged[i] = node.kwargs[pname]
256
+ return names, merged
257
+
258
+ def extract_input_manifest(self) -> list[dict]:
259
+ """Walk top-level ``var = input.*(...)`` decls into an InputDef list.
260
+
261
+ Each entry: ``{title, type, default[, min, max, step, options]}``. The
262
+ optional keys are emitted only when the corresponding signature
263
+ argument is a const literal; a bound/option referencing a non-literal
264
+ is omitted (never crashes). One pass over ``self.ctx.ast.body``.
265
+ """
266
+ out: list[dict] = []
267
+ for stmt in self.ctx.ast.body:
268
+ if not (
269
+ isinstance(stmt, VarDecl)
270
+ and isinstance(stmt.value, FuncCall)
271
+ and self._is_input_call(stmt.value)
272
+ ):
273
+ continue
274
+ node = stmt.value
275
+ func_name, namespace = self._resolve_callee(node.callee)
276
+ names, merged = self._merged_args(node, func_name, namespace)
277
+ title = self._get_input_title(node, var_name=stmt.name)
278
+ default_node = self._get_input_default(node)
279
+ default_val = (
280
+ self._literal_or_none(default_node)
281
+ if default_node is not None
282
+ else None
283
+ )
284
+ if namespace == "input":
285
+ form_type = self._FORM_TYPE.get(func_name, "string")
286
+ else:
287
+ # Plain ``input(...)``: Pine types the result by its defval.
288
+ # The codegen already emits the matching scalar getter, so the
289
+ # manifest must mirror that — infer from the resolved default's
290
+ # Python type. ``bool`` MUST be tested before ``int`` because
291
+ # ``isinstance(True, int)`` is True. A None/non-literal default
292
+ # falls back to "string".
293
+ if isinstance(default_val, bool):
294
+ form_type = "bool"
295
+ elif isinstance(default_val, int):
296
+ form_type = "int"
297
+ elif isinstance(default_val, float):
298
+ form_type = "float"
299
+ elif isinstance(default_val, str):
300
+ form_type = "string"
301
+ else:
302
+ form_type = "string"
303
+ entry: dict = {
304
+ "title": title,
305
+ "type": form_type,
306
+ "default": default_val,
307
+ }
308
+ # Pull min/max/step/options by signature param name; emit only
309
+ # const literals so the override form never references a runtime
310
+ # value it can't reproduce.
311
+ if names:
312
+ idx = {n: i for i, n in enumerate(names)}
313
+ for key, pname in (("min", "minval"), ("max", "maxval"), ("step", "step")):
314
+ i = idx.get(pname)
315
+ if i is not None and i < len(merged) and merged[i] is not None:
316
+ v = self._literal_or_none(merged[i])
317
+ # bool is an int subclass — exclude it from numeric bounds
318
+ if isinstance(v, (int, float)) and not isinstance(v, bool):
319
+ entry[key] = v
320
+ oi = idx.get("options")
321
+ if oi is not None and oi < len(merged) and merged[oi] is not None:
322
+ opts_node = merged[oi]
323
+ elems = getattr(opts_node, "elements", None)
324
+ if elems is not None:
325
+ vals = [self._literal_or_none(e) for e in elems]
326
+ # any non-const element -> omit the whole options list
327
+ if vals and all(isinstance(v, str) for v in vals):
328
+ entry["options"] = vals
329
+ out.append(entry)
330
+ return out
@@ -444,6 +444,11 @@ class CallVisitor:
444
444
  return "0"
445
445
  if func_name in SKIP_FUNC_NAMES and namespace is None:
446
446
  return "0"
447
+ # max_bars_back(var, num): a history-depth DIRECTIVE, not a value.
448
+ # Its effect is captured in CodeGen._compute_max_bars_back_cap (which
449
+ # sizes every Series<T> ring buffer), so the call itself emits nothing.
450
+ if func_name == "max_bars_back" and namespace is None:
451
+ return "0"
447
452
 
448
453
  # request.* calls
449
454
  if namespace == "request":
@@ -10,9 +10,14 @@ Buckets:
10
10
  * HARD_REJECT_FUNC / HARD_REJECT_NAMESPACE - calls that have no PineForge
11
11
  semantics at all (e.g. ``request.financial``, ``ticker.*``).
12
12
  * DIVERGENT_VARS - built-in variables whose PineForge value diverges from
13
- TradingView (e.g. ``bar_index`` depends on data window, ``last_bar_index``
14
- is wrongly aliased in codegen). Reported as WARNING — these often appear
15
- in visual or logging code that does not affect trade outcomes.
13
+ TradingView. Most are reported as WARNING (e.g. ``bar_index`` depends on the
14
+ data window, ``timenow`` is not wall-clock) — these often appear in visual or
15
+ logging code that does not affect trade outcomes. A subset
16
+ (DIVERGENT_VARS_ERROR: ``last_bar_index`` aliased to the *current* bar index,
17
+ ``time_close`` aliased to the bar *open* timestamp) are silent MIS-ALIASES:
18
+ they produce a plausible-looking but wrong value that flows straight into
19
+ trade logic, so a backtest would be silently wrong. Those are escalated to
20
+ ERROR (rejected) rather than merely warned.
16
21
  * NOT_YET - calls the runtime could support but the transpiler does not yet
17
22
  emit (e.g. ``max_bars_back``, bare ``barssince``).
18
23
  * request.security - only ``symbol`` / ``timeframe`` / ``expression`` allowed,
@@ -131,16 +136,25 @@ HARD_REJECT_NAMESPACE: dict[str, str] = {
131
136
  }
132
137
 
133
138
  # Built-in variables whose PineForge value diverges from TradingView semantics.
134
- # Demoted to WARNING — many real strategies use bar_index / time_close in
135
- # logging or visual logic that does not affect trade outcomes. The checker
136
- # still flags divergence so users see the risk.
139
+ # Most are reported as WARNING — many real strategies use bar_index / timenow in
140
+ # logging or visual logic that does not affect trade outcomes. The checker still
141
+ # flags divergence so users see the risk.
142
+ #
143
+ # DIVERGENT_VARS_ERROR is a SUBSET that is escalated to ERROR (rejected): these
144
+ # are silent MIS-ALIASES, not merely data-window divergences. They return a
145
+ # plausible value that is the WRONG quantity (last_bar_index -> current bar
146
+ # index; time_close -> bar OPEN timestamp) and that value flows directly into
147
+ # trade logic, so the backtest would be silently wrong. A WARNING is not enough.
137
148
  DIVERGENT_VARS: dict[str, str] = {
138
149
  "bar_index": "bar_index depends on the data window; PineForge and TradingView produce different values for the same script.",
139
- "last_bar_index": "last_bar_index is incorrectly aliased to the current bar index in PineForge codegen.",
150
+ "last_bar_index": "last_bar_index is aliased to the CURRENT bar index in PineForge codegen (not the index of the last bar); backtest would be silently wrong — rejected.",
140
151
  "timenow": "timenow is aliased to the current bar timestamp in PineForge; it is not real wall-clock time.",
141
- "time_close": "time_close is aliased to the bar open timestamp in PineForge; it does not represent the bar close time.",
152
+ "time_close": "time_close is aliased to the bar OPEN timestamp in PineForge; it does not represent the bar close time; backtest would be silently wrong — rejected.",
142
153
  }
143
154
 
155
+ # Subset of DIVERGENT_VARS escalated from WARNING to ERROR (see comment above).
156
+ DIVERGENT_VARS_ERROR: frozenset[str] = frozenset({"last_bar_index", "time_close"})
157
+
144
158
  BARSTATE_APPROX_VARS: dict[str, str] = {
145
159
  "barstate.islast": "barstate.islast is always false in PineForge batch backtests.",
146
160
  "barstate.ishistory": "barstate.ishistory is always true in PineForge batch backtests.",
@@ -191,8 +205,12 @@ STRATEGY_EXIT_PRICE_PARAMS: frozenset[str] = frozenset({
191
205
  })
192
206
 
193
207
  # Implementable but currently silent in codegen -> reject loudly.
208
+ #
209
+ # max_bars_back was here ("silently dropped") but is now WIRED: codegen sizes
210
+ # every Series<T> ring buffer to the requested depth via the engine's
211
+ # ``Series<T>(int max_len)`` ctor (include/pineforge/series.hpp). It is no
212
+ # longer rejected — see CodeGen._compute_max_bars_back_cap.
194
213
  NOT_YET_FUNC: dict[str, str] = {
195
- "max_bars_back": "max_bars_back is silently dropped by the codegen.",
196
214
  "timeframe.from_seconds": "timeframe.from_seconds is not yet implemented; codegen would emit 'false' and silently produce wrong TF strings.",
197
215
  }
198
216
 
@@ -386,6 +404,12 @@ class SupportChecker:
386
404
  # request.security (barmerge.* gaps/lookahead values). While > 0 the
387
405
  # UNSUPPORTED_CONST_NAMESPACES rejection is suppressed.
388
406
  self._const_arg_ctx_depth: int = 0
407
+ # id()s of Identifier/MemberAccess nodes that are the *callee* of a
408
+ # FuncCall. A divergent built-in NAME used as a call target (e.g. the
409
+ # session-aware ``time_close("D")`` function, which is distinct from the
410
+ # bare ``time_close`` variable) must NOT be flagged as a divergent
411
+ # variable read. Populated as _visit_FuncCall descends into children.
412
+ self._callee_node_ids: set[int] = set()
389
413
 
390
414
  # -- Public API --
391
415
 
@@ -629,6 +653,12 @@ class SupportChecker:
629
653
  def _visit_FuncCall(self, node: FuncCall) -> None:
630
654
  ns, name = _qualified_name(node.callee)
631
655
 
656
+ # Mark the callee so the generic child-walk does not treat a divergent
657
+ # built-in *function* name (e.g. ``time_close("D")``) as a divergent
658
+ # *variable* read. The call's own semantics are validated here.
659
+ if node.callee is not None:
660
+ self._callee_node_ids.add(id(node.callee))
661
+
632
662
  if ns is None and name is None:
633
663
  self._visit_children(node)
634
664
  return
@@ -918,8 +948,9 @@ class SupportChecker:
918
948
  "code into the strategy script).",
919
949
  )
920
950
  return
921
- if node.name in DIVERGENT_VARS:
922
- self._warn(
951
+ if node.name in DIVERGENT_VARS and id(node) not in self._callee_node_ids:
952
+ emit = self._err if node.name in DIVERGENT_VARS_ERROR else self._warn
953
+ emit(
923
954
  node,
924
955
  f"{node.name} diverges from TradingView semantics in PineForge.",
925
956
  hint=DIVERGENT_VARS[node.name],
@@ -945,8 +976,13 @@ class SupportChecker:
945
976
 
946
977
  def _visit_MemberAccess(self, node: MemberAccess) -> None:
947
978
  chain = _resolve_member_chain(node)
948
- if chain is not None and chain in DIVERGENT_VARS:
949
- self._warn(
979
+ if (
980
+ chain is not None
981
+ and chain in DIVERGENT_VARS
982
+ and id(node) not in self._callee_node_ids
983
+ ):
984
+ emit = self._err if chain in DIVERGENT_VARS_ERROR else self._warn
985
+ emit(
950
986
  node,
951
987
  f"{chain} diverges from TradingView semantics in PineForge.",
952
988
  hint=DIVERGENT_VARS[chain],
@@ -1004,14 +1040,21 @@ class SupportChecker:
1004
1040
  if isinstance(node.object, Identifier) and node.object.name == "syminfo":
1005
1041
  if node.member not in SUPPORTED_SYMINFO:
1006
1042
  self._err(node, f"syminfo.{node.member} is not implemented in PineForge runtime.")
1007
- elif (
1008
- self._in_conditional_depth > 0
1009
- and node.member in self._SYMINFO_SILENT_GAP_FIELDS
1010
- ):
1043
+ elif node.member in self._SYMINFO_SILENT_GAP_FIELDS:
1044
+ # These fields silently return na in current PineForge. Warn on
1045
+ # EVERY read — not just inside an if/ternary condition — because
1046
+ # a field used directly in a plain expression (e.g. ``x =
1047
+ # syminfo.pricescale * 2``) slips out as na with no signal too.
1048
+ # The conditional phrasing is kept where it applies.
1049
+ extra = (
1050
+ " condition will always be false."
1051
+ if self._in_conditional_depth > 0
1052
+ else " any expression using it will be na."
1053
+ )
1011
1054
  self._warn(
1012
1055
  node,
1013
- f"syminfo.{node.member} returns na in current PineForge; "
1014
- "condition will always be false. "
1056
+ f"syminfo.{node.member} returns na in current PineForge;"
1057
+ f"{extra} "
1015
1058
  "Will be backfilled by pineforge-data product.",
1016
1059
  )
1017
1060
  self._visit_children(node)
@@ -12,6 +12,14 @@ const GLUE = `__GLUE__`;
12
12
  const post = (m) => self.postMessage(m);
13
13
  let transpileJson = null;
14
14
 
15
+ // Hex-encode the SHA-256 of an ArrayBuffer using the worker's WebCrypto.
16
+ async function sha256Hex(buf) {
17
+ const digest = await crypto.subtle.digest("SHA-256", buf);
18
+ return Array.from(new Uint8Array(digest))
19
+ .map((b) => b.toString(16).padStart(2, "0"))
20
+ .join("");
21
+ }
22
+
15
23
  async function init() {
16
24
  try {
17
25
  const pyodide = await loadPyodide({ indexURL: "/pyodide/" });
@@ -21,6 +29,19 @@ async function init() {
21
29
  const archiveRes = await fetch(`/pyodide/${manifest.archive}`);
22
30
  if (!archiveRes.ok) throw new Error(`fetch /pyodide/${manifest.archive}: ${archiveRes.status}`);
23
31
  const buf = await archiveRes.arrayBuffer();
32
+ // Defensive integrity check: verify the archive bytes against the manifest's
33
+ // sha256 BEFORE unpacking/running. Verify-if-present — older manifests that
34
+ // predate the sha256 field are accepted unchanged (forward/backward compat).
35
+ if (manifest.sha256) {
36
+ const actual = await sha256Hex(buf);
37
+ if (actual !== manifest.sha256) {
38
+ post({
39
+ type: "init-error",
40
+ error: `codegen archive sha256 mismatch — expected ${manifest.sha256} got ${actual}`,
41
+ });
42
+ return;
43
+ }
44
+ }
24
45
  pyodide.unpackArchive(buf, "gztar", { extractDir: "/codegen" });
25
46
  pyodide.runPython(GLUE);
26
47
  const fn = pyodide.globals.get("transpile_json");
@@ -0,0 +1,7 @@
1
+ //@version=6
2
+ strategy("T")
3
+ // last_bar_index is aliased to the CURRENT bar index in PineForge codegen, so a
4
+ // backtest reading it would be silently wrong -> hard reject (ERROR).
5
+ isLast = bar_index == last_bar_index
6
+ if isLast
7
+ strategy.close_all()
@@ -0,0 +1,9 @@
1
+ //@version=6
2
+ strategy("T")
3
+ // The bare ``time_close`` variable is aliased to the bar OPEN timestamp in
4
+ // PineForge codegen, so a backtest comparing against it would be silently
5
+ // wrong -> hard reject (ERROR). (The session-aware time_close(...) FUNCTION is
6
+ // a separate, supported builtin and is not rejected.)
7
+ expired = time >= time_close
8
+ if expired
9
+ strategy.close_all()