Repository navigation
Enforce strict count parity and fix Pine semantics gaps - #60
Merged
Merged
Conversation
Bugs solved: - Honor the Pine ta.stdev/ta.variance biased argument. - Use sample denominator length - 1 for biased=false and preserve the default biased denominator. Validation: - cmake --build build -j4 - ctest --test-dir build -R test_ta_indicators_extras --output-on-failure - scripts/verify_corpus.py --all --quiet
Store strategy.exit profit/loss tick offsets on pending exits and materialize their limit/stop prices from the live position entry price. This lets retained brackets attached to pending entries fill on the same bar as the entry, matching TradingView TP/SL behavior without strategy-specific logic.
TradingView fixed-offset labels such as GMT+1 use the human-readable sign convention, while POSIX TZ uses the reverse sign. This caused session/time gates to fire in the wrong UTC window for strategies using explicit GMT/UTC offsets.\n\nAdd a shared timezone normalizer, route ScopedTimezone through it, expose it for generated code, and cover session and calendar bucket behavior.
Add a syminfo metadata bar_index_offset for validation feeds whose local OHLCV starts after TradingView's hidden chart-history origin. Expose pine_bar_index() and pine_last_bar_index() helpers so codegen can shift Pine-visible indices while engine internals remain zero-based.
luisleo526
added a commit
that referenced
this pull request
Sep 27, 2026
…irst extreme gap-fills there as a forced fill (R5 integration INT27, round 2: the gate sweep's regressed probe) INT27's gate sweep (exp-r5-int27-20260927, engine d3b753c + codegen a4259656, against rebaseline exp-rebaseline2b-20260926 on engine d093560) refused the merge on one script, officialjackofalltrades-aureate-market-architecture-strategy-joat, on four lanes: OANDA:XAUUSD 15m (count +1), OANDA:EURUSD 15m (+3), BINANCE:BTCUSDT 15m (+7) and the scraped BINANCE:ETHUSDT.P lane (+4), every one excellent on the baseline. On XAUUSD the entry price moves from trade #60 on (3266.82 -> 3261.29). Bisect (the probe's own feeds and the pinned Lab verifier on spark, one library per pick boundary): 0631e04 (the INT27 merge fix) and c54f939 (PAR-ORDERS-3 findings 1-2) book the baseline trades (e8107dece428); e5efd18 -- PAR-ORDERS-3 finding 4, bc5f7a21: after the matcher's fill at a resting request's own level on a bar's first extreme, the recalculation's orders act from that extreme -- books 477b4cca24af, as every later commit. Mechanism, on the XAUUSD bar 2025-04-16 00:30 UTC (O 3261.715, H 3266.82, L 3261.29, C 3263.885, low first), traced in a scratch copy of the adapter: the strategy.exit limit leg carried from the previous bar (below the price) fills at the open; its recalculation re-enters, filled at the open too (the refill); that entry's recalculation re-places the exit, whose limit 3260.5585 is already through, so exit() arms it at the first extreme (later_same_open: StopLimit{W1 3261.29, 3260.5585}), where the path gap-fills it at 3261.29 -- TradingView's trade #59 exit. Its placement carries no forced_execution_price, so begin_coof_recalc left coof_fill_forced_ false, and finding 4's rule in coof_next_waypoint read the fill as the matcher's at the limit's own level ON the extreme: the market re-entry filled at W1, 3261.29. TradingView books it at the second extreme, 3266.82 (#60), as it books a market order after the control's forced fill (pa3-f4-point-w1-mkt-*). Main advanced every such fill to the next waypoint, which is why it matched. Fix, in finding 4's own classification: begin_coof_recalc counts the fill of an exit limit armed as a StopLimit whose stop satisfies its level (for a long, stop >= limit: exit()'s endpoint_satisfies, read through the placement's projection_position_side as closing_long was) AT that stop (coof_fill_at_path_point) as forced. Such a fill is a gap fill onto the point, not the matcher's at the limit's own level -- even with that level exactly on the extreme, which TradingView answers the same way. A StopLimit whose stop does not satisfy its level fills later at the level itself and stays a level fill. No state is added; the flag is the recalculation's transient. Tapes (lab tv --no-note, NYSE:F 15, 2025-07-01 .. 07-08, ws-report-v1, rangeProof covered; tests/fixtures/second_extreme_orders/int27-*): lot E's exit limit X, placed at bar j-1's close beyond bar j's first extreme, fills at bar j's open; X's recalculation re-enters E at the open; E's recalculation places X2 at X's level, already through, which the path gap-fills at the first extreme; X2's recalculation re-enters E. Long j = 28, 61 (low-first), short j = 13, 44 (high-first); the level beyond the extreme (int27-open-xlimit-w1-reentry-*), exactly on it (-xlimit-at-w1-) and as the limit leg of a bracket with a far stop, the probe's form (-xbracket-w1-). TradingView books the re-entry at the second extreme on all six (long 11.90 / 11.58, short 11.66 / 11.67; tvTradesSha256 d713d16b long, 3fe435c0 short). Rows: tests/test_second_extreme_order_tapes.cpp, six variants, 36 rows, 342 checks. Fail-before, against d3b753c: 12 fail -- rows 3 and 6 of every int27 tape re-enter at the first extreme (long 11.84 / 11.55, short 11.68 / 11.72). After: 342 of 342 pass, every pa2 and pa3-f4 row unchanged. The probe (spark, the lane templates' feeds and environment facts, the Cloud Run runner's case environment), engine trade-set sha256: XAUUSD 15m d093560 e8107dece428, d3b753c 477b4cca24af, fixed e8107dece428 EURUSD 15m d093560 c139231711f4, d3b753c 78c241198232, fixed c139231711f4 BTCUSDT 15m d093560 30a00613d41f, d3b753c 39e944861bc0, fixed 30a00613d41f ETHUSDT.P d093560 163550bd8f95, d3b753c 0374608317dc, fixed 163550bd8f95 every fixed lane excellent 100.0 with count delta 0, the baseline sweep's own trade sets (lab trades show). Hash: the eleven v19 witness harvests on this tree are byte-identical to INT27's (f-09dafee5); no pinned value moves, so there is no re-pin. Docs: the design page names the boundary; the test and fixture README describe the tapes. The +17 lines in pine_adapter.cpp move 121 of 1725 anchors, carried by the exact line map from d3b753c (0 stuck); check_doc_anchors 1725 1725 0, stale-carried 0, doc lint clean. Co-Authored-By: Claude Opus 5.5 (1M context) <[email protected]>
luisleo526
added a commit
that referenced
this pull request
Sep 27, 2026
…fills at extremes, O(bars) drawing checkpoints, dynamic TA lengths, finer-than-feed security, zoned session speed (#291) * Read a request.security finer than every supplied feed as na instead of stopping the run TradingView reads a lower timeframe from that timeframe's own bars and keeps the last 2,000,000 of them. On BINANCE:ETHUSDT.P 15m and 1D over 2025-04-01..2026-05-01, request.security(tickerid, "5S", close) is na up to 2026-01-04 22:45 UTC and "15S" up to 2025-05-18 03:15 UTC; the 1m series (568,783 bars) is whole. A gaps_on read is na on the 27 chart bars that hold no 5S bar. A chart bar holding no loaded bar of the requested timeframe reads na (lab tv pf-krunerr-ltf-horizon, -ltf-values, -ltf-count2, 2026-09-26). The campaign lanes' finest bars are 1m, so a "5S" or "15S" site has no loaded bar anywhere, yet validate_security_timeframes refused it: "request.security: requested timeframe '5S' is finer than input '1'". That stopped all 14 rows of karmasantosh773-growwithcare-final-5s-master-strategy (baseline e69aa1f7). Where the host already supplied bars finer than the chart -- the auxiliary slice, or an input finer than the script timeframe -- such a site is now marked no_loaded_bars and never fed, so it and its TA read na throughout. A chart fed without intrabar bars (input_tf == script_tf) keeps the refusal, unchanged: it asks the host for finer bars, and the verifier's split-feed retry keys on it. This is Pine request.security semantics, so it lives in the source adapter (ADR-0001 rule 1); the kernel is untouched. The flag is folded into the source security hash only when set, so every site that loads bars keeps the digest it had: no witness moves. tests/test_security_finer_than_feed.cpp (release-only, floor 678 -> 679): 15m chart + 1m slice with "5S"/"15S"/"30S" beside a served "1" site, a 1D chart, a 1m input aggregated to 15m, and the unchanged refusal of "5S" and "5" on a chart fed alone. At 0d76a099 the first three stop with the population's own error (9/22 checks). test_pine_security_state_hash carries the new field's mutation row. Doc anchors into the header and ci_verify.py move with the inserted lines. Co-Authored-By: Claude Opus 5.5 (1M context) <[email protected]> (cherry picked from commit d82fb6f04b07e6922fd406abc4968d7dd1fb5788) INT27 pick note: every source, header and test hunk applied unchanged. The docs conflicts were citation digits only (the lane's header and ci_verify.py insertions against INT26's re-anchored pages), merged token by token; INT27's single re-anchor pass sets every digit on the integrated tree. The release floor is INT26's 703 plus this row, 704. * Keep an after-close Muhurat session's own slice on the calendar split feed The nifty-1d lane's chart feed -- TradingView's own NSE:NIFTY 1D bars -- holds Muhurat sessions held after the regular close: Monday 2022-10-24 18:15 IST and Sunday 2023-11-12 18:15 IST. prepare_aux_security_chart_ranges keys a calendar bar by the session it covers (11febbc7, for OANDA's break-stamped dailies), and such a bar covers the NEXT regular session, the key of the native bar after it. The strictly-increasing key guard then stopped every split-feed run on the lane: "native chart feed trading-period identities must be unique and strictly increasing with an auxiliary security feed". karmasantosh773-growwithcare-final-5s-master-strategy on nifty-1d reached it once its "5S" sites stopped refusing. The calendar route partitions the auxiliary bars by the native timestamps, [chart_ts[i], chart_ts[i + 1]), which are strictly increasing (checked just above), so the Muhurat bar and the next regular bar keep their own slices. The guard now refuses only a calendar key that runs backwards; intraday keys are the routing labels themselves and stay strictly increasing. Only runs that stopped here change. tests/test_security_finer_than_feed.cpp gains the scenario: Friday, the Sunday Muhurat and Monday as three native bars with two 1m bars each read 12 / 22 / 32 from a "1" site, and a "5S" site stays na. Before this commit it stops with the duplicate-identity error (27/30 checks). Doc anchors into pine_aux_security.cpp move with the inserted lines. Co-Authored-By: Claude Opus 5.5 (1M context) <[email protected]> (cherry picked from commit 281186653c29b74a55137449c41685e17e2aad44) INT27 pick note: the source and test hunks applied unchanged; the one docs conflict was citation digits only, merged token by token (INT27's single re-anchor pass sets every digit on the integrated tree). * Kernel: session-day facts on a certified cycle of an exchange zone resolve no calendar interval per bar (R5 lane PERF-ZONED) PERF-KEDGE recovered KERNEL-EDGE's per-bar cost on UTC calendars only. On every other zone present_session_day still resolved the bar's script interval through the calendar memo at every bar, and read the label and both neighbours through it: a New York 5-minute FeedTolerant run cost 1.73x the instructions of 1a0e7ea1 (+2,443 Ir a bar), a Tokyo 1-minute run 1.22x (+3,439). native_calendar::cycle_certificate certifies the session day holding an instant when the zone makes its cycle read from that day alone: UTC or a fixed offset, or, under glibc or macOS, a TZif v2+ zone whose 64-bit table covers the reach (22 days around the cycle, widened by the spacing) and whose transitions there move the offset by at most 3 hours, between offsets within 14 hours of UT, never backwards while keeping the daylight-saving flag, and at least 8 days apart, each read back from libc (localtime on both sides, chained). Then every civil time in reach resolves to the first instant the wall clock reaches it, whatever was resolved before: one reading is found from any start; the two readings of a fold that flips the flag are both found (glibc's mktime probes a week at a time for the flag asked, and the spacing puts that probe on the fold's own side; macOS's mktime keeps no state) and resolve_stamp keeps the earlier; a gap resolves to the move itself inside the 14-hour search. So the cycles tile, each instant's local date is within a day of its cycle's open date, the memo's candidate lookup finds exactly that day, and no other day holds its instants. The zone is asked first, around the instant, and a day is resolved only where it holds: a refused certificate asks the calendar nothing. On a certified cycle present_session_day reads an instant in one of the day's spans in session on the day's ordinal, and an instant whose fixed bucket (fixed_bucket_ms, the calendar's own unit) meets no span out of session, resolving nothing. A bucket that reaches a span from outside one, every instant a certificate refuses, the walk and the scheduled close make the calls they always made. Measured on spark (instructions:u, A725 core 12): - zoned configs, 3000 bars idle, main 1a0e7ea1 / f1f3febd / this commit: NY 5m tolerant 1.7294x -> 1.0000x, NY 1m tolerant 1.7648x -> 0.9993x, Tokyo 1m tolerant 1.2201x -> 1.0003x; every canonical and tolerant config of NY, Tokyo, Chicago, London, Kolkata and UTC at most 1.0008x main; - the 100 public slots against f1f3febd: median 0.9952 (magnifier on), 0.9942 (off), no slot above 1.0; against main 1.0013 / 1.0001; - the budget workload: +0.41% over main at f1f3febd, +0.32% here. Identity (spark, f1f3febd against this commit, byte for byte): 100 slots x magnifier off/on with trade digests, equity and broker_state_hash; the 132-configuration battery on 8 host variants with every hash column; the KERNEL-EDGE probes and the AUDIT4 acid tests; PERF-KEDGE's facts battery (9,216 rows); a new 60-window zoned facts battery (45,600 rows: 2024 changes of New York, Chicago, Denver, Los Angeles, St John's, Havana, Santiago, London, Berlin, Dublin, Sydney, Lord Howe, Auckland, Chatham, Casablanca, Troll; Sao Paulo 2018/19, Tehran 2021, Apia and Tongatapu at +14, Caracas, Pyongyang; constant zones; and the refused folds and jumps of Tokyo 1887, Sitka and Juneau 1867, Apia 2011, Kwajalein 1969, Moscow 2011/2014, Recife 2000, New York 1883 and 2040, Amsterdam 1937, Manila 1844); the Pine witness replay. - native_calendar.cpp / native_calendar_memo.hpp: cycle_certificate, fixed_bucket_ms, SessionDayMemo::libc_local_reads() (a derived cost reading), the TZif v2+ table reader, and tz_read_resource shared with the identity digest. - native_execution_consumer: the certified-cycle cache (four entries, the last hit first), certified_point, certified_interval_meets_span; the PERF-KEDGE UTC member calendar_is_utc() is gone (a UTC calendar certifies every cycle). ADR-0001 rule 2: a generic capability of the run's own calendar -- its zone is data, the same for every venue -- with no spec field, switch or Pine vocabulary, and no answer moves. The only platform condition picks the libcs whose mktime the proof reads; elsewhere TZif zones take the exact path. Nothing is hashed: the facts fold into no digest and the new members are derived memos. Witness, tests/test_native_session_day_zoned.cpp (kernel-only): certificates at real transitions (New York, Chicago, London, Sydney, Lord Howe 2024 certified where the host's table lists them; Tokyo, Kolkata, a fixed offset, Apia at +14, Sitka's +14:58:47 and Moscow 2015 certified; Tokyo 1887, Sitka 1867, Apia 2011, Kwajalein 1969, Moscow 2014, Recife 2000, New York 2040 and POSIX zones refused, a refused certificate reading nothing), each certified cycle checked against the memo-free session_day_at; the same tapes under each TZif zone and its POSIX twin (never certified) present identical facts at every decision point over 8 windows, 7 sessions and 12 runs each, plus the magnifier, seconds and undetected paths (700 runs, 0 mismatches); and New York and Tokyo FeedTolerant batches resolve no interval for their facts where their twins resolve one a bar. Fail-before at f1f3febd: "no member named 'libc_local_reads' in 'pineforge::native_calendar::SessionDayMemo'". 17 of 19 mutants fail it; the two that survive loosen guards no zone in the host's database reaches (the 14-hour offset bound, the libc chain check). The PERF-KEDGE witness's probe reads the memo's UTC decision directly and its header records the change. Floors: kernel 278 -> 279, release 679 -> 680, PR registration 660/660/669 -> 661/661/670 (ci_verify.py, its self-test pin and docs/ci.md). 24 doc anchors carried through the exact line map from f1f3febd; the 6 that cite the two rewritten floor lines set by hand (ci_verify.py:253, :365). Co-Authored-By: Claude Opus 5.5 (1M context) <[email protected]> (cherry picked from commit 27e1f384f1063c13efe3961ff58b8a0c6410c425) INT27 pick note: the lane's base f1f3febd is PERF-KEDGE's tip, which INT26 carries as a3b4b971/debbd7f1. Every source, header and test hunk applied unchanged against INT26's text (each file's patch is byte-identical to the lane's), and no other caller of PERF-KEDGE's calendar_is_utc() is left on the merged tree. The floors are INT26's plus K-RUNERR's plus this lane's row: kernel 287 run (288 registered), release 705, PR registration 686/686/695 (ci_verify.py, its self-test pin and docs/ci.md). The docs conflicts were citation digits, merged token by token (INT27's single re-anchor pass sets every digit on the integrated tree), and the one floors paragraph, rewritten with the merged counts. * Pine v6 strategy() defaults: TradingView's tapes, replayed under the configuration the generated constructor declares TradingView changed three Pine v6 strategy() defaults around 2026-09-24T20:45Z. For a v6 script that omits them it now uses initial_capital = 100000, default_qty_type = strategy.percent_of_equity and default_qty_value = 100 (100 whatever the type: 100 contracts under strategy.fixed, 100 of the account currency under strategy.cash), where it used 1000000 / strategy.fixed / 1. Pine v5 keeps the old three, and none of the other strategy() defaults moved: lane TV-DEFAULTS exported 244 controlled lab-tv tapes of synthetic probes (Pine v5 and v6; BINANCE:BTCUSDT, NYSE:F, BINANCE:ETHUSDT.P and CME_MINI:ES1! 15; each parameter omitted, at its old default and at a value that moves the tape). The defaults are Pine policy -- what an omitted strategy() argument means, by language version -- so the kernel does not learn them (ADR-0001 boundary rules 1 and 2: a default capital or order size means nothing to a venue that states its own account, and a kernel knob would be hash-visible surface for a value every host already declares in its NativeRunSpec; engine.hpp's initial_capital_ member default is overwritten from the spec at every run begin). PineStrategyConfig's member defaults stay 1000000 / fixed / 1 -- Pine v5's, and what every hand-built source host relies on -- and pineforge-codegen (cg/tvdefaults d7e095f) declares the v6 values in the generated constructor for a script that omits them. test_tv_strategy_defaults replays seven of those tapes (BINANCE:ETHUSDT.P 15, 2025-04-01..05-01, byte-for-byte in tests/fixtures/tv_strategy_defaults) through the Pine adapter over 521 corpus 15m bars (bars.inc), under the configuration the generated constructor declares for each probe, and requires every trade the tape closes inside them -- 6 of 42 or 8 of 58, two v6 margin refusals among the six -- to be the engine's on TradingView's 0.01 tick and 0.0001 lot: an omitted capital (100% of 100000), an omitted type (1% of equity), an omitted value (100 contracts; 100 USDT), all three omitted, and two probes that declare every one, which run the same configuration either way. Under the configuration the pre-lane constructor declared, the host's defaults for the omitted arguments, each of the five omitted-argument probes misses its tape. The row pins the engine side; codegen's test_e2e_strategy_defaults pins the emission end to end on the same tapes and fails on codegen a4259656. Floors: the row is source-bound, so RELEASE_MIN_TESTS 678 -> 679 and the PR registration floors debug/sanitizers/native 659/659/668 -> 660/660/669 (the kernel floor stays 277); the floor notes are folded into the comment lines already there, so no line the documentation anchors moves. No hash witness moves and no engine source changes; the cheatsheet and configuration page state the v6 defaults. Co-Authored-By: Claude Opus 5.5 (1M context) <[email protected]> (cherry picked from commit 4b457291ab1100c812384923e8de7eb442a6a3f8) INT27 pick note: the engine half of lane TV-DEFAULTS only -- the row, its seven tapes, the docs and the floors. The lane's second commit, 1320b01d (the corpus gitlink f989e36 -> b73f8d6 and its baseline line), is not picked: its six initial_capital pins wait for the next corpus regeneration, and the corpus stays at b40aa8e. The test, fixture and docs hunks applied unchanged; the floors are INT26's plus K-RUNERR's and PERF-ZONED's plus this row: release 706, PR registration 687/687/696 (ci_verify.py, its self-test pin and docs/ci.md); the kernel floor does not move. * Kernel: a retained lower bar walks its own four turning points, and a bar that traded nothing at one price is one point (R5 lane MAG-INTRABAR) - NativeExecutionConsumer::deliver_intrabar_script: a lower bar the direct four-sample path declines (a leg of zero length, an open at its own low) is walked through its four corners, the repeated one included, instead of the general ENDPOINTS sampler's uniform fill -- every sample is a margin check point since PAR-MARGIN, so the fill measured a price the bar never printed there; a bar with volume 0 and open = high = low = close is one discrete sample, walked once. - ADR-0001: the rule-2 row (a mechanism correction, no knob). - tests/test_native_intrabar_turning_points.cpp (kernel-only, new row): the open-at-its-low sub-bar's marks are 60 60 90 85 and the call armed at that open is booked at 60; a volume-0 one-price sub-bar gives one mark. Against 3ea143e5's library 4 of its 21 checks fail (the uniform 77.5, no call, 12 marks on bar 3); against the v18 closure the TU does not compile ("no member named 'IntrabarSample'"). - tests/test_magnifier_ordered_sampler.cpp: a lower sub-bar with a zero-length leg is expected at its corners. - Floors: kernel 279 -> 280, release 681 -> 682 (the new row registers in both); docs/ci.md and the floor citations follow; published anchors re-anchored to the moved kernel lines. No witness value moves; the 65 ctest rows that run a lower path or the magnifier pass unchanged on this commit. Co-Authored-By: Claude Opus 5.5 (1M context) <[email protected]> (cherry picked from commit 4a89056ce2faba4605db1b79e97d7178640aecb4) INT27 pick note: the lane's base 3ea143e5 is PAR-MARGIN-2's tip, which INT26 carries under other shas. The kernel, test and CMake hunks applied unchanged (each file's patch is byte-identical to the lane's). The ADR-0001 rule-2 row sits after PAR-MARGIN-2's margin_segment_origin row, above H-DOCGATES' inventory rows, where INT26 put the other mechanism rows. The floors are INT26's plus the earlier INT27 picks plus this row: kernel 288 run (289 registered), release 707, PR registration 688/688/697 (the lane counted no PR registration floor; its kernel row registers in all three excluded profiles). The other docs conflicts were citation digits, merged token by token (INT27's single re-anchor pass sets every digit on the integrated tree). * Adapter: the bar magnifier walks TradingView's own intrabars -- its table's timeframe, each owned by the chart bar of its last minute (R5 lane MAG-INTRABAR) TradingView's magnifier does not walk the host's 1-minute feed: its help-centre table picks the intrabar per chart timeframe (1 -> 10S, 5 -> 30S, 10 -> 1, 15 -> 2, 30 -> 5, 60 -> 10, 240 -> 30, 1D -> 60, 3D -> 240, 1W -> 1D), each intrabar is the symbol's regular bar anchored at the session day's open and cut at its close, and it belongs to the chart bar that holds its LAST minute. - source::tradingview_intrabar_timeframe / tradingview_magnifier_bars (include/pineforge/source/magnifier_intrabars.hpp, src/source/ magnifier_intrabars.cpp): build that path from the input feed on its own grid -- the chart bar's open as a volume-0 print when its first intrabar straddles into it, each owned intrabar aggregated and stamped at its first input (a straddler one millisecond after the print), the chart bar's close as a print when its last minute belongs to the next bar's intrabar. The input comes back unchanged when the intrabar cannot be built from it (a 1- or 5-minute chart needs 10S / 30S bars) or a calendar interval is unresolved. - PineExecutionAdapter::project hands that path to IntrabarPath::lower_tf. - calc_on_order_fills on that path (72 of 72 TradingView cascades): the open point is the walked intrabar's own Open, re-admitted at every intrabar (PineStrategyHost::on_native_sub_bar -> PineScheduler::sub_bar_complete); next_input_waypoint looks the bar up on the lower path and returns the intrabar's open, first and second extreme, then the next intrabar's open (never its close; a print goes straight to the next open), with the adapter's own same-point rule (coof_fill_at_path_point) for a booked tick; a market entry or close whose next point is the next intrabar's open stays a plain market order (coof_waits_for_next_sub_bar), which the kernel fills there even at the price the recalculation stands at. broker_bar reads the walked intrabar. - Tests: test_magnifier_tradingview_intrabars (the table, grids, sessions, ownership; 168 checks) and test_adapter_magnifier_intrabar_tapes (TradingView's request.security_lower_tf intrabars for 1m..1D on ETH, NSE:NIFTY and NYSE:F; three bracket tapes; the two refill tapes; 1160 checks), new rows, fail-before "magnifier_intrabars.hpp file not found". The differential's intrabar rows now assert TradingView's rows on all 20 magnified tapes (0130 no longer recorded). Re-pinned to TradingView's cascade: the calc_on_order_fills twin's adapter lots and test_adapter_coof_relower's refill trace -- 100 @900000, then the straddler 100, 100, 99, 101 @900001, then 100.1 @960000 (were 100, 100, 99, 101, 100.25 @900000, 100.1 @960000). - Fixtures: tests/fixtures/magnifier_intrabars (13 lab tv exports of the lane's own scripts, bars_1m.inc, README); intrabar_margin README updated. - Docs: magnifier page (the intrabars a Pine strategy walks), pine-to-native use_bar_magnifier row, native-engine margin passages, ADR-0001 (the adapter's path and refill points; the kernel row's writer), design rows CT9 and E4; anchors re-anchored. - Floors: release 682 -> 684 (two source-bound rows). No witness value moves (the release ctest's witness rows pass unchanged). Co-Authored-By: Claude Opus 5.5 (1M context) <[email protected]> (cherry picked from commit 9df16c24b6186b9adadaedfd2d467e76ecffe9e3) INT27 pick note: the lane's base 3ea143e5 predates INT26's PAR-ORDERS and PAR-ORDERS-2 picks, which rewrote the same recalculation code. Composed, each lane's intent kept: - PineExecutionAdapter::close keeps PAR-ORDERS-2's second-extreme rule on the chart path (coof_close_at_second_extreme) and gains this lane's next-intrabar rule on a lower path (coof_close_next_sub_bar); entry() merged cleanly the same way. - test_adapter_coof_relower's refill lots and test_native_calc_timing_twin's adapter lots take this lane's prices (TradingView's cascade on the 2-minute intrabars: 100, then 100, 100, 99, 101, then 100.1) at PAR-ORDERS' instants (every magnified fill dated at its chart bar's open, 900000); both rows pass on the merged tree, and both lanes' sentences are kept. - tests/CMakeLists.txt: git's clean merge closed H-MEASURE's fixture list twice and repeated its margin row; the list is closed once, with this lane's tape row inside it. - Floors: release 709, PR registration 690/690/699 (the lane counted no PR registration floor; its three rows register in all three excluded profiles). - Docs: the design rows CT9 and E4 keep INT26's re-anchored text and gain this lane's sentences; the ADR row of the kernel's lower-bar samples takes this lane's text above H-DOCGATES' rows; the rest were citation digits, merged token by token. On this commit H-MEASURE's test_magnified_aggregated_tape, a row the lane's base did not carry, fails: its v3 row 2 now books TradingView's fill (a move toward the tape), and v2/v3 row 5 moves away from it -- the next commit (INT27 merge) settles both. * INT27 merge: a magnified recalculation's market order after the matcher's fill at an intrabar's second extreme fills there R5 lane MAG-INTRABAR's base (PAR-MARGIN-2's tip) did not carry INT26's PAR-ORDERS-2 picks or H-MEASURE's test_magnified_aggregated_tape, so the two lanes' rules met first on this tree. - PAR-ORDERS-2 (H-MEASURE Finding 6d): the matcher's fill of a resting request at its own level AT a bar's second extreme ends the leg there, and the recalculation's market order fills at that extreme; a fill the adapter forced there advances. It is written for the chart path (PineExecutionAdapter::coof_fill_at_second_extreme); on a lower path the magnified run met it only by accident: the old next_input_waypoint took an off-grid extreme's booked tick for a fill short of it and returned the extreme. - MAG-INTRABAR: a magnified run walks TradingView's 2-minute intrabars, and after an intrabar's second extreme the next fill point is the next intrabar's open (mi-coof-refill*, 72 of 72 cascades, every one a market order's -- forced -- fill), with the same-point rule that no longer mistakes a booked tick for a fill short of its print. Together, on hm-mag-diff-v2 and -v3 bar 19 (NYSE:F, 14:15 ET) PX's limit fills at its own level on the high of the 14:26 intrabar (11.715, booked 11.72), its second extreme, and the ML entry its recalculation places went to the 14:28 intrabar's open, 11.71; TradingView books 11.72 on both tapes. PineScheduler::next_input_waypoint now returns the second extreme itself for the matcher's own (unforced) fill there, so the market order fills at it, and keeps the next intrabar's open for a forced fill: row 5 of both magnified replays is TradingView's again, and every cascade, bracket and margin tape of MAG-INTRABAR still passes (test_adapter_magnifier_intrabar_ tapes, test_adapter_coof_relower, test_native_calc_timing_twin, and the 95 magnifier / intrabar / lower-path / margin / calc_on_order_fills / POOC / extreme-order rows all pass). No hash witness moves (the eleven witness rows pass unchanged). The same test's v3 row 2 (magnified), a recorded divergence (11.58 where TradingView books 11.54), flipped to TradingView's with MAG-INTRABAR's kernel commit alone: PX's limit fills on the leg to the high of a sub-bar that opens at its own low (bar 6, the 11:01 ET minute), and the kernel now walks such a bar through its four turning points instead of the sampler's uniform fill, so the entry books that high, 11.54. It stays exact on the 2-minute intrabars. The row is no longer recorded, and the file's header says why. Co-Authored-By: Claude Opus 5.5 (1M context) <[email protected]> * Adapter: an exit a recalculation places on a fill at a bar's extreme reads that fill -- a level fill leaves no leg in flight, a forced one is read from the extreme itself (R5 lane PAR-ORDERS-3, findings 1 and 2) exit()'s calc_on_order_fills classification took the recalculating fill's remaining leg from next_source_path_waypoint(point) alone: - a fill AT the bar's first extreme -- the matcher's fill of a resting request at its own level there -- read the whole next leg as the in-flight remainder of its own (9f7a025c pine_adapter.cpp:9026-9048), so a priced exit born there was forced onto the second extreme (Limit{endpoint}); TradingView books it at its own level on the leg to that extreme (lab tv pa2-i2-level-w1-{long,short}{,-pooc}); - a fill forced onto an OFF-grid first extreme books its tick (11.425 -> 11.43, 11.645 -> 11.65), which next_source_path_waypoint read as a fill short of the low, so the exit was a plain limit and the next entry filled at the second extreme; TradingView starts the next leg at the extreme (lab tv pa2-i2-point-w2-long{,-pooc}). The classification now reads the fill as 4985dcaa does for entries and strategy.close: at_own_extreme (coof_fill_at_path_point on the phase's own extreme) and coof_fill_forced_ tell a level fill, which ends its leg and leaves no remainder in flight (fill_ends_leg), from a forced one, whose next waypoint is read from the extreme itself. Rows (tests/test_second_extreme_order_tapes.cpp; 25 of its 132 checks fail on the base): every RECORDED boundary row flips to exact -- pa2-i2-level-w1-long rows 1-6 (both variants), -short rows 1, 2, 5, 6, -short-pooc rows 1, 2 (still compared on its first cycle: finding 3), and pa2-i2-point-w2-long rows 2, 3, 5, 6 (2, 3, 5 under process_orders_on_close). The exit tapes' rows 5 and 7 / 1 stay RECORDED (finding 4). Hash: publication witness ConfigFlags103 moves (its X limit, placed by the recalculation on a limit entry's level fill at bar 24's low 99.75, fills at its level 100.75, not at the high 103.00); re-pinned once in the lane's hash commit. Co-Authored-By: Claude Opus 5.5 (1M context) <[email protected]> (cherry picked from commit fe50e34118c7bb20a342198e3137a2193a968da6) INT27 pick note: the adapter and test hunks applied unchanged (each file's patch is byte-identical to the lane's); the docs conflicts were citation digits, merged token by token (INT27's single re-anchor pass sets every digit on the integrated tree). The lane's hash values (publication ConfigFlags103) fold into the single INT27 v19 hash re-pin, not this commit. * Adapter: after the matcher's fill at its own level on a bar's first extreme, the recalculation's orders act from that extreme (R5 lane PAR-ORDERS-3, finding 4) coof_next_waypoint advanced every order a non-first-open recalculation placed to the waypoint AFTER its fill's point (fe50e341 pine_adapter.cpp:5834), so after a fill AT a bar's first extreme a market entry, strategy.close, close_all or a market strategy.order waited for the second extreme or the next open, and an exit stop already through was held to the leg's end or deferred to the next open. H-MEASURE Finding 6d and 4985dcaa had settled the second extreme; the first was predicted, not taped. The lane exported the tapes that decide it (lab tv, NYSE:F 15m, 2025-07-01..08, 20 tapes, tests/fixtures/second_extreme_orders/pa3-f4-*): - after the matcher's fill of a resting request at its own level ON the first extreme (a limit entry A there), TradingView fills a market entry B, strategy.close("A"), close_all and a market strategy.order AT that extreme (pa3-f4-level-w1-{mkt,close,closeall,order}-*), fills A's exit stop, already through, AT it (-xstop-*), and fills a stop entry B between the extremes at its own level on the leg to the second extreme (-bstop-*); - the two shapes ab9714be's rows pinned hold the same: a STOP entry exactly on the extreme then the market add (pa3-f4-stop-w1-mkt-*), an EXIT limit exactly on it then the market re-entry, whose own exit limit, already through, fills where the path next re-crosses its level (pa3-f4-xlimit-w1-reentry{,-tp}-*); - a fill forced onto the first extreme still starts the next leg: the control pa3-f4-point-w1-mkt-* fills B at the second extreme. coof_next_waypoint returns the point itself for a matcher's (not forced) fill at an extreme (pine_adapter.cpp:5841); exit() fills a stop already through at the point the fill ended its leg on (pine_adapter.cpp:9118-9127), never staged behind the recalculation or deferred as a wrong-side stop (:9379, :9391). That leg is a stop AT the point, not a market leg: the recalculation executes market newborns in place, which a cohort-bound leg (close_entries_rule "any": Owner BindCohort, refused by current execution since af7618d0) cannot take, and a market leg would then book the point's price on a later bar (the xstop tapes replayed under "any": bar 5 @11.46 for TradingView's bar 4 @11.46; with the stop, exact). The same reading moves the second-extreme exit tapes: a stop B's recalculation places on the second extreme, reached on the leg to the close, fills at its own level there instead of the close's tick. Rows: tests/test_second_extreme_order_tapes.cpp 285 checks (54 fail on fe50e341, 79 on the base): pa2-i2-exit-w2-long{,-pooc} rows 5, 7 and -short{,-pooc} row 1 flip RECORDED -> exact; the 20 pa3-f4 tapes, 93 rows, exact (48 of them fail on fe50e341). Frozen rows moved with their notes, toward the tapes: - test_calc_on_order_fills EndpointMarketAddProbe chart row, and its frozen twin test_calc_on_order_fills_l4c: the add's lot 90 (second extreme) -> 105 (the first extreme the stop entry's fill ended its leg on; pa3-f4-stop-w1-mkt-*); tests/twin_parity_inventory.json pins it as an observable rewrite, INVENTORY_SHA256 264aef4a -> cb035ede; - the L0 oracle tests/oracle/test_oracle_coof.cpp (twin test_native_oracle_coof_l2) and its copy test_coof_cascade_eligibility, row R1: the cascade re-entry 90 (W2) -> 101 (W1) and its tp exit bar 2 -> 1 (pa3-f4-xlimit-w1-reentry{,-tp}-*); tests/oracle.sha256 test_oracle_coof.cpp 647f8a24 -> e006f064, tree f39b54fe -> f25b1dd2. CHECK counts unchanged (census 791). Hash: quiet-bar CalcOnFills, Random10, Random20 (chart, both runs each), publication ConfigFlags103 (X's stop, 99.75 at the point its entry's level fill ended the leg on, fills there) and seven live-state digests move; re-pinned once in the lane's hash commit. Co-Authored-By: Claude Opus 5.5 (1M context) <[email protected]> (cherry picked from commit bc5f7a212050f2dd97f03e6da201f7d8def9bc0e) INT27 pick note: every adapter, test, oracle and fixture hunk applied unchanged (each file's patch is byte-identical to the lane's). The twin inventory merged cleanly with INT26's; its pin in check_twin_parity.py is the merged file's own sha256 (b0066ba1, the lane's cb035ede being its own inventory's), and check_twin_parity.py and check_oracle_sha256.py pass. The docs conflicts were citation digits, merged token by token (INT27's single re-anchor pass sets every digit on the integrated tree). The lane's hash and behaviour pins (quiet-bar, publication, live-state) are harvested on the integrated tree: its behaviour half lands after this lane's picks, its hash values in the single INT27 v19 hash re-pin. * Adapter: a process_orders_on_close limit entry fills at the close that placed it when the close's tick reaches it, with or without calc_on_order_fills (R5 lane PAR-ORDERS-3, finding 3) The post-calculation close pass (fill_pooc_close_entries) tested a pure limit entry placed by the bar's close calculation against the RAW close, and skipped every limit under calc_on_order_fills (bc5f7a21 pine_adapter.cpp:16649-16671). TradingView reads the close's TICK, as the pass already did for a stop, with or without calc_on_order_fills (lab tv pa3-f3-pooc-limit-{long,short}{,-coof}, NYSE:F 15m, 2025-07-01..08, tests/fixtures/pooc_limit_close): a sell limit at 11.76 over a raw 11.755 close (tick 11.76) and at 11.86 over 11.855 fill at that close; a buy limit at 11.65 over a raw 11.655 close (tick 11.66) and at 11.74 over 11.745 rest, and so does every limit only the bar's range reached -- each fills on the next bar's touch. PAR-ORDERS-2 recorded the short case on pa2-i2-level-w1-short-pooc, cycle 2 (bar 31: TradingView fills A's sell limit at the close its high already reached, the engine on bar 32). pure_limit no longer excludes calc_on_order_fills, and at_close compares the close's tick for a limit as for a stop (pine_adapter.cpp:16654-16675). Rows: tests/test_pooc_limit_close_tapes.cpp (new, 28 checks; 4 fail on bc5f7a21 and on the base: both short tapes' j = 22 and j = 31 entries a bar late); tests/test_second_extreme_order_tapes.cpp compares pa2-i2-level-w1-short-pooc whole again, rows 1-5 (was its first cycle, rows 1-2): 288 checks, 3 fail on bc5f7a21, 82 on the base. Release floor 682 -> 683 (+1 test_pooc_limit_close_tapes, source-bound; the ci_verify.py:359 citations in CONTRIBUTING.md and docs/pages/contributing-llm.md follow the line). No hash witness moves beyond the lane's earlier commits. Co-Authored-By: Claude Opus 5.5 (1M context) <[email protected]> (cherry picked from commit 1550a694e859e7606bee7fad6081fe54594a4307) INT27 pick note: the adapter and test hunks applied unchanged (each file's patch is byte-identical to the lane's). tests/CMakeLists.txt: git's clean merge closed H-MEASURE's fixture list after MAG-INTRABAR's row and left this lane's row outside it; the list is closed once, with both rows inside. The floors are the earlier picks' plus this row: release 710, PR registration 691/691/700 (ci_verify.py, its self-test pin and docs/ci.md). The design page's close-pass paragraph keeps both insertions -- this lane's limit sentence, then INT26 round 2's re-entry bracket sentences; the other docs conflicts were citation digits, merged token by token. The lane's b65cee22 (its hash re-pin) is not picked: its behaviour half follows, and its hash values fold into the single INT27 v19 hash re-pin. * PAR-ORDERS-3: the trades and transcripts its fixes move, pinned (INT27: the behaviour half of b65cee22) R5 lane PAR-ORDERS-3's own re-pin, b65cee22 ("PAR-ORDERS-3 v19 hash re-pin"), moves hash values and behaviour together. INT27 folds its hash values into the single INT27 v19 hash re-pin, whose tool refuses any non-hash change, so the behaviour it pins lands here, with the fixes that move it. Harvested on this tree with each TU's own switch (PINEFORGE_QUIET_BAR_HARVEST, PINEFORGE_D2D_PUBLICATION_HARVEST, PINEFORGE_V19E_HARVEST and the other eight), at the pick boundary before the lane (0631e045, which reproduces every pinned value) and after each of its three commits, and compared field by field with the pins before the picks, the lane's b65cee22 and its base 1550a694: - fe50e341 (findings 1 and 2) moves publication ConfigFlags103's digest only; bc5f7a21 (finding 4) moves it again, and the quiet-bar and live-state rows below; 1550a694 (finding 3) moves nothing -- the lane's own attribution. - test_adapter_quiet_bar: the trade digests of CalcOnFills/0/*, Random10/0/* and Random20/0/* (CalcOnFills keeps every trade and renumbers Trade::entry_incarnation), and the boundary counts Random10/0/* 69 -> 67 and Random20/0/* 70 -> 69, equal to the lane's. The same runs the lane moved; INT26's picks had moved their trade digests too, so the digests are this tree's. The list sits in the pinned file. - test_adapter_live_state_equivalence: 6 of 108 transcript digests (the transcript holds no hash value) -- reversals seeds 314187, 1780393 and 3246599, brackets 314188 and 1780394, chains 314189, the lane's seeds; INT26's picks had moved each of them before, so the digests and counts are this tree's (reversals 314187: 168 -> 196 trades, 3246599: 147 -> 149; brackets 314188: 144 -> 134, 1780394: 95 -> 96; chains 314189: 62 -> 75). The lane's seventh, chains 1780395, a digest-only move on its tree, does not move here. The list sits in the data file. - test_publication_witness: ConfigFlags103's digest only, a hash value; nothing lands here. Until the INT27 v19 hash re-pin, test_adapter_quiet_bar and test_publication_witness fail on those hash values only (15 values over the 6 quiet-bar runs, ConfigFlags103's digest); every other witness row passes. (behaviour half of commit b65cee223f1839df0989da9fba24501788417c01) Co-Authored-By: Claude Opus 5.5 (1M context) <[email protected]> * Drawing arenas: share records between checkpoint copies so a COOF run costs O(bars) calc_on_order_fills checkpoints the generated script state at every script bar (pine_scheduler_native.cpp: snapshot at the bar open, restore before the close execution, commit after it, two restores per fill recalculation), and the generated hooks copy each DrawingArena by value. A record is never forgotten -- delete and max_*_count eviction only tombstone it -- so every copy cost O(every drawing ever created) and a drawing COOF run was quadratic in bars (job-2892: ~239 s CPU on NYSE:F 15, ~12,950 s on ETH 15). DrawingArena's records now live in a store that is a vector until the arena is copied, exactly as before, and nothing in a vector is ever shared. A copy is built as blocks of 32 under a 32-way radix trie plus a tail block, and a copy of a block store -- or a store assigned from one -- shares every block; a write clones only the blocks and nodes on its path that another copy still shares. Under the scheduler's sequence the first snapshot copies the vector (O(records), once, at the first bar) and the restore assigns the copy back, so from then on a checkpoint copy or restore is O(1) for records plus O(live) for the order_ deque (at most max_*_count ids), and a script execution pays for the blocks it writes. The generated by-value checkpoint needs no codegen change. An arena that is never copied keeps the vector and inlines only the vector paths; every block path is out of line. Every observable -- ids, liveness, every field of live and dead records, order() (the *.all and eviction order), every pf_* result and exception -- is unchanged. Getters read through a const path that never unshares. Eviction tombstones a record before it leaves order_, so a refused allocation in that write leaves the arena consistent; a moved-from arena is empty and a self-move keeps the arena. Rows: - test_drawing_checkpoint: differential against the pre-lane vector arena (verbatim) over random create/delete/eviction/set_* and every pf_* getter/setter/copy, interleaved with snapshot/restore/commit and arbitrary copy graphs, past three trie levels, every checkpoint compared whole before it is dropped; the scheduler's sequence across a run reset; refused allocations, including partway through copying a block of labels; the cost pins (after the first bar an unchanged checkpoint copies no record and allocates the same for 10,000 and 40,000 records; synth-label-coof's churn copies <= 64 records per execution and the checkpoint steps' bytes stay per-step bounded, N -> 2N ratio <= 2.25). Under AddressSanitizer the random and cost rows run fewer steps (its fake stack made the row take 575 s). - test_coof_drawing_checkpoint_cost: synth-label-coof through the Pine host with calc_on_order_fills and fills, 4,000 vs 8,000 bars, the same bounds on record copies and on what the checkpoint hooks allocate. - test_coof_drawing_rollback_tape: TradingView's coof-drawing-rollback tape (CG-POPFIX, 41 trades) replayed through the Pine host: all 41 trades identical in times, prices, quantities and both comments (x2 == n). Fail-before (the three rows against the old drawing.hpp): every cost pin fails (30,000,000 record copies for an unchanged 10,000-record arena; ratio 4.000), every exactness row passes. Co-Authored-By: Claude Opus 5.5 (1M context) <[email protected]> (cherry picked from commit 52f0395087ac6b8d9e83475ab1e664c71df058aa) INT27 pick note (late pick, accepted 2026-09-26 22:47, placed after the last scheduled pick and its behaviour half; the list names no place): drawing.hpp, the three rows and the fixture applied unchanged. git's clean merge put this lane's fixture-dir block inside TV-DEFAULTS' `if(TARGET test_tv_strategy_defaults)` block, before its endif(); each block stands on its own. The lane's floors and doc anchors (0d651058) are not picked: INT27's floors item recounts the floors (this lane: kernel +1, release +3, each PR registration floor +3) and INT27's single re-anchor pass sets the digits. * Compute ta.* calls with a simple or series length as TradingView does TradingView accepts a length that is neither a constant nor an input. PineForge refused every such call at transpile time. This adds the Pine runtime those calls lower onto, in the source layer (include/pineforge/source/pine_ta_length.hpp, src/source/pine_ta_length.cpp): - A simple length (fixed for the run: a syminfo preset, an input-string ternary) is answered exactly as the constant. FirstCallBound builds the fixed-length class from the call's first execution; simple_ta_length stops the run on 0, a negative length or na, with TradingView's text. - A series length for ta.highest / ta.lowest / ta.highestbars / ta.lowestbars re-windows every call over the site's own bar history (skipped bars hold the last executed source), through a cached extremum whose growth, poison and late-first-execution rules fit 5,647 recorded TradingView calls of 35 synthetic call sites with no mismatch (SeriesHighest, SeriesLowest, SeriesHighestBars, SeriesLowestBars). - ta.supertrend compiles a series factor but reads it once: PineSupertrend is the Pine reference with the first execution's factor, warm-up included (1,200/1,200 recorded bars). TradingView refuses a series length for ta.rma / ema / rsi / atr / dmi / macd / kc / hma / tsi / rci and supertrend's atrPeriod at compile time, so those only ever see a simple length. Three rows replay the lab tv tapes (test_ta_series_length_extremes, test_ta_series_length_supertrend, test_ta_simple_length); the release floor moves 678 -> 681. No kernel translation unit changes. Co-Authored-By: Claude Opus 5.5 (1M context) <[email protected]> (cherry picked from commit ea7021ac08529bbecc54f41364af2b23ebd142cd) INT27 pick note (late pick, accepted 2026-09-26 23:20, placed after the late pick K-DRAWSNAP): the source-layer runtime, the library's source list and the three rows applied unchanged (each file's patch is byte-identical to the lane's). Its floor hunk (release 678 -> 681 on its base) is not applied: INT27's floors item recounts the floors with its three rows (release and the three PR registration floors +3; the kernel floor does not move, its TUs reach the source layer). The paired codegen commits land in the codegen integration. * INT27 (iii): the lower-lookup shape witness times user CPU, so the allocator's page faults no longer decide it test_native_intrabar_lower_lookup bounds the cost of 16,000 script bars (and a four times longer lower feed) by 6x that of 4,000 bars; a scan of the whole feed per script bar reads 16-18. It timed process CPU (std::clock), and on the lab's x86 cloud hosts it read 6.19-6.28 where NTU and spark read about 5.9 -- and on this tree it fails on spark too. The excess is not the code the row times. Split on spark (gcc 13, one pinned X925 core, 4,000 / 16,000 bars x64, best of three): - process time: 0.15 s / 0.98 s, ratio 6.12-6.61 (main d0935605: 0.10 s x32 / 0.59-0.61 s, 5.71-5.88); - of the large leg's 0.98 s, 0.38-0.41 s is SYSTEM time; the small leg's is 0.00-0.004 s. The allocator maps the large leg's buffers afresh on every run -- a first-touch page fault per page -- where the small leg reuses its heap; - user time: 3.88-4.00 on this tree, 3.91-3.95 on main. R5 lane PERF-ZONED exposed it: its certified fixed-offset cycles (this spec runs at UTC+5) took the per-bar calendar cost out of both legs, so the fixed fault cost weighs more (6b601ef0, right after that pick: 6.50-6.63). tests/ratio_timing.hpp gains ratio_timing::user_cpu_seconds() (getrusage RUSAGE_SELF's ru_utime; std::clock where getrusage does not exist), the lane CI-FLAKE helper file every ratio row shares, and this row samples it. The legs, the calibration (100 ms of the same clock, the doubling of tests/ratio_timing.hpp) and the x6 bound are unchanged. The guarded property still fails on a real quadratic regression: with deliver_intrabar_script's lower_bound replaced by the pre-K24 scan of the whole feed (scratch copies only, never committed), the row reads - 18.11 on spark under user time (18.19 under the old process time), - 17.04 on the M4 Max, and fails "ratio < kShapeBound" on both; unmutated it reads 3.88-4.00 on spark and 3.88-4.36 on the M4 Max. The value half and every pin are untouched. Co-Authored-By: Claude Opus 5.5 (1M context) <[email protected]> * INT27 (iv): the effective-strategy report reads the configuration the generated constructor declares The provenance's "strategy" block (scripts/run_strategy.py's --fingerprint-json and docker/run_json.py's "fingerprint") is the seed of strategy() defaults, then what the TU's constructor declares, then the run's strategy_overrides. Its parser read only pre-R4-C member writes (`initial_capital_ = ...;`), and pineforge-codegen has since filled a source::PineStrategyConfig (`cfg.initial_capital = 100000.0;`, `cfg.default_qty_type = static_cast<int>(QtyType::PERCENT_OF_EQUITY);`) and handed it to configure_pine_strategy, so every report showed the seed whatever the script declared (R5 lane TV-DEFAULTS, follow-up 3) -- and with TradingView's new Pine v6 defaults declared in the constructor, a v6 script's report named capital and sizing it did not run with. parse_strategy_params now reads the constructor's PineStrategyConfig assignments (the variable its declaration names; enum members stored as int, `static_cast<int>(...)` unwrapped, an integer index mapped too) and, for older TUs, the member writes as before. The seed is PineStrategyConfig's member defaults (the values it already held; its comment named engine.hpp's pre-R4-C members). The block's keys are unchanged, so the margins and calc_on_order_fills the constructor also declares stay out of it. Both copies are the one helper block, byte for byte. - scripts/fingerprint_self_test.py: two fixtures in the constructor's current form -- every field declared, including a decoy StrategyOverrides line outside the constructor, and a sparse one whose undeclared fields are the struct's defaults. 284 checks pass; against the previous helpers 6 of them fail (every cfg-form field read, the declared values, the sparse defaults). - Over the corpus's 312 TUs at b40aa8e (pure parsing, both copies agree): before, 311 reports equal the seed exactly (the other only by its inputs.json overrides); after, 88 change -- pyramiding 81, default size 63, capital 62, commission 61, slippage 59, sizing type 25, process_orders_on_close 4, commission type 3 -- and every numeric literal a constructor declares equals its report's value unless an override replaces it. analyzer-anvil-percent-costs-01, for one: fixed / 1 / 1000000 / 0 / 0 -> percent_of_equity / 7.5 / 100000 / 0.08 / 2. Provenance only: nothing the run executes reads the block, so no trade moves (the corpus parity step runs this harness). Co-Authored-By: Claude Opus 5.5 (1M context) <[email protected]> * INT27 (i): the 1.0.0 entry says what INT27's picks change for a user Added to "Behaviour that moves results against 0.13.1", each a sentence a user can act on: - Pine v6's current strategy() defaults for an omitted initial_capital, default_qty_type or default_qty_value (100000, percent_of_equity, 100), which pineforge-codegen 1.0.0 declares; v5 and a hand-built PineStrategyConfig keep 1000000 / fixed / 1; declare the three to keep the old sizing. - calc_on_order_fills after a resting order's own-level fill on a bar's high or low: the recalculation's market orders, closes and passed exit stops fill at that point, an exit limit placed on the first extreme's fill is live at its level on the leg to the second, a forced fill still moves on, an off-grid extreme's booked tick is that extreme, and under the bar magnifier a market order after such a fill at an intrabar's second extreme fills there (the existing second-extreme sentence, widened). - process_orders_on_close: a limit entry at the placing bar's close fills there when the close's tick reaches it, with or without calc_on_order_fills. - The bar magnifier walks TradingView's own intrabars, built from the finer feed, and what a 1/5-minute chart and an exchange-listed daily chart still walk; a zero-length-leg lower bar walks its four turning points and a volume-0 one-price bar is one point. - A request.security finer than every supplied feed reads na instead of stopping the run; a daily run with an auxiliary feed no longer stops on an after-close session (NSE Muhurat). - A ta.* call with a simple or series length (the late pick's runtime, which pineforge-codegen 1.0.0 lowers onto) and what is still refused. A new "Performance" section: a calc_on_order_fills strategy that draws no longer slows with every drawing it made -- the late pick's shared checkpoint copies; codegen has checkpointed the script state, drawings included, on every fill recalculation since codegen v0.9.0, which 0.13.1 paired with. A new "Reports and tools" section: the provenance's strategy block records what the generated constructor declares, so such fingerprints change and the trades do not (INT27 item iv). The session-day speedup on exchange-zone charts has no line: it removes a cost introduced after 0.13.1, and no answer moves. The lower-lookup timing witness is a test change. No lane name is cited. Co-Authored-By: Claude Opus 5.5 (1M context) <[email protected]> * INT27 (ii): the ctest floors are the integrated tree's own counts Counted with `ctest -N` per profile, each build dir configured with ci_verify.py's own configure argv (no compiler launcher, as CI has none), on this tree and on main d0935605: profile main d0935605 INT27 floor release 703 716 RELEASE_MIN_TESTS 716 kernel 287 reg / 286 run 290 reg / 289 run KERNEL_MIN_TESTS 289 debug 684 697 EXCLUDED 697 sanitizers 684 697 EXCLUDED 697 native 693 706 EXCLUDED 706 The thirteen rows, and the lanes that moved each floor (no row left): - K-RUNERR: test_security_finer_than_feed (release and the three PR registration floors); - PERF-ZONED: test_native_session_day_zoned (source-free: kernel, release, PR registration); - TV-DEFAULTS: test_tv_strategy_defaults (release, PR registration); - MAG-INTRABAR: test_native_intrabar_turning_points (source-free: kernel, release, PR registration), test_magnifier_tradingview_intrabars and test_adapter_magnifier_intrabar_tapes (release, PR registration); - PAR-ORDERS-3: test_pooc_limit_close_tapes (release, PR registration); - K-DRAWSNAP (late pick): test_drawing_checkpoint (source-free: kernel, release, PR registration), test_coof_drawing_checkpoint_cost and test_coof_drawing_rollback_tape (release, PR registration) -- the deltas the late-picks list names (kernel +1, release +3, each PR floor +3), its own floors commit 0d651058 not picked; - K-TA-DYNLEN (late pick): test_ta_series_length_extremes, test_ta_series_length_supertrend and test_ta_simple_length (release, PR registration; their TUs reach the source layer, so the kernel floor does not move) -- the lane's own floor hunk (release 678 -> 681 on its base) not applied. K-RUNERR and MAG-INTRABAR had counted no PR registration floor on their branches; the picks added them, and this commit folds the per-pick floor notes into one INT27 block per floor. The self-test's EXCLUDED pin and docs/ci.md's floors paragraph say the same numbers. Co-Authored-By: Claude Opus 5.5 (1M context) <[email protected]> * INT27 v19 hash re-pin Inside the unreleased v19 epoch; no epoch token moves. Every witness pin harvested once on the integrated tree, each pinned TU compiled with its own harvest switch against the tree's library (INT26's harvest set: the eleven witnesses PINEFORGE_R1/F9/P1/P4/QUIET_BAR/L5/P7/D2D_PUBLICATION/K1/V19E _HARVEST and PF_HOST_VIEW_MEMO_DUMP), and at every pick boundary that could move one, so each moved value names its pick: - 0631e045 (after K-RUNERR, PERF-ZONED, TV-DEFAULTS, MAG-INTRABAR and the INT27 merge) reproduces every pinned value: those picks move none; - c54f939e (PAR-ORDERS-3 findings 1-2), e5efd189 (finding 4), 9dc3fc08 (finding 3, which moves none); - 4160b3e3 and 6fa516ec, the late picks K-DRAWSNAP (after the lane's behaviour half) and K-TA-DYNLEN: their eleven harvests are byte-identical to 9dc3fc08's; - this tree (INT27's items (iii), (iv), (i), (ii)): identical again. 16 hash values over 7 rows move, all by R5 lane PAR-ORDERS-3; the trade digests, counts and live-state transcripts its fixes move were pinned with them (5c6988c2, the behaviour half of the lane's own re-pin b65cee22, which is not picked): - test_adapter_quiet_bar: 15 of 816 values, CalcOnFills/0/*, Random10/0/*, Random20/0/* (the chart-path runs; finding 4, the first-extreme rule); - test_publication_witness: 1 of 156, ConfigFlags103's digest (findings 1-2, then 4: its X limit placed on a limit entry's level fill at bar 24's low fills at its level, and X's stop, already through at the point that fill ended the leg on, fills there); - 0 moved: report_relower 72, recording_hash_witness 267, continuation_view 227, receipts_in_place 334, command_allocations 32, lookup_index_witness 948, host_view_memo 13, calendar_hash_witness 12; live_state holds no hash value. Old -> new (each pinned file carries the same list): test_adapter_quiet_bar CalcOnFills/0/1: boundary 0xbd9feba11a355c84ull -> 0x109b8bbd2db3c39cull, rows 0xbd62a54cd2c27075ull -> 0x4990637dd008c142ull, final_hash 0x8e716ca55979f5e4ull -> 0x23caae4465e49b8dull [PAR-ORDERS-3 f4] test_adapter_quiet_bar CalcOnFills/0/0: boundary 0xbd9feba11a355c84ull -> 0x109b8bbd2db3c39cull, final_hash 0x8e716ca55979f5e4ull -> 0x23caae4465e49b8dull [PAR-ORDERS-3 f4] test_adapter_quiet_bar Random10/0/1: boundary 0x82933908492fe6aeull -> 0x53a92b8342582407ull, rows 0x839a10fa6478c692ull -> 0x337fd61947e125a0ull, final_hash 0x6907e89e2f502bd7ull -> 0xfb592dc1ad328c0bull [PAR-ORDERS-3 f4] test_adapter_quiet_bar Random10/0/0: boundary 0x82933908492fe6aeull -> 0x53a92b8342582407ull, final_hash 0x6907e89e2f502bd7ull -> 0xfb592dc1ad328c0bull [PAR-ORDERS-3 f4] test_adapter_quiet_bar Random20/0/1: boundary 0xad83f25bfdab1b50ull -> 0x6d39d123fcb64c3cull, rows 0x103b25042e1313deull -> 0x4350e4a911697ba6ull, final_hash 0xb27d00f43fad75a1ull -> 0x2fff8a1132834fe4ull [PAR-ORDERS-3 f4] test_adapter_quiet_bar Random20/0/0: boundary 0xad83f25bfdab1b50ull -> 0x6d39d123fcb64c3cull, final_hash 0xb27d00f43fad75a1ull -> 0x2fff8a1132834fe4ull [PAR-ORDERS-3 f4] test_publication_witness ConfigFlags103: digest 0x9e412b4fb357ae55ull -> 0x275174bdfd481a1bull [PAR-ORDERS-3 f1-2, PAR-ORDERS-3 f4] The tool (INT26's repin_int26.py with this epoch's notes) refuses any non-hash change: 7 of 7 mutated harvests stop it (a quiet-bar trade digest and boundary count, a publication trade count, a live-state transcript, a host-view-memo fingerprint field, a calendar witness row field, a report_relower curve statistic). After the write the same harvest reproduces every pin (0 moved) and the eleven witness rows pass. Co-Authored-By: Claude Opus 5.5 (1M context) <[email protected]> * INT27: the doc-revert gate starts after main's newest merged pull request when a checkout has no main ref INT27's lab remote preflight failed doc-reverts on a tree whose own commits pass it: "21 commits since this gate landed: 5 unnamed sentence deletions or reverts". The lab's remote hosts check out a bundle with no branch refs, so default_base() found no origin/main or main and the walk ran back from HEAD to the gate's first commit -- which, on main's squashed history, is the squash merge of INT26 itself, d0935605 (#290). It carries the whole branch's deletions under the pull request's title: H-THIN's `owns_lot_excursions()` sentence (introduced by e7350f7), PAR-ORDERS' two F7 E14 sentences (39cc605) and two E20 probe-tail sentences (b80a082). Each was named by its own commit on r5/int26, whose remote preflight passed; the squash cannot name them again. `check_doc_reverts.py --base 0d76a099 --head d0935605` reproduces the 5; CI, which has origin/main, never judges the squash (its merge base with a branch is the squash itself). Every lane based on main after INT26 hits the same failure on a lab remote host. With no branch ref, default_base() now takes the newest first-parent ancestor of HEAD whose subject ends in a pull request number (` (#N)`, the subject GitHub writes for a merged pull request on main), HEAD included: the merge base CI would find. Every commit after it is judged as before; with none, the walk still starts at HEAD and stops before the gate's first commit. --base, PINEFORGE_DOC_REVERT_BASE and the origin/main / main merge base keep their precedence, and the replay mode is unchanged. - scripts/test_check_doc_reverts.py: a squash-titled commit that deletes an unnamed sentence is the base without a main ref (the walk judges the one commit after it, and the squash judged alone still fails), and an unnamed deletion after a merged pull request still fails. 12 tests pass. - docs/ci.md states the rule. Co-Authored-By: Claude Opus 5.5 (1M context) <[email protected]> * INT27 (v): every doc anchor re-anchored once, on the integrated tree One pass over every page check_doc_anchors.py scans, after the last pick, the behaviour pins and the hash re-pin, so the digits are the final tree's. Digits only: with every citation's digits blanked, each of the 8 pages is byte-identical to its parent (181 lines change). How, in order: 1. The multi-origin exact map (INT24's int24_exact_reanchor.py with --exclusive-first): main d0935605 first, then each lane's tip in pick order (K-RUNERR 28118665, PERF-ZONED 27e1f384, TV-DEFAULTS 4b457291, MAG-INTRABAR 9df16c24, PAR-ORDERS-3 1550a694; the late picks K-DRAWSNAP and K-TA-DYNLEN touch no page): each anchor carried through an exact difflib line map from the tree its digits were written against. 1725 anchors: 293 moved, 1394 kept, 38 stuck (digits a pick's digit merge composed, which no origin carries). 2. INT26's anchor_origin_fix.py --relaxed over every INT27 commit and the lane tips: 15 anchors by the same line and position on main's page, carried through the exact map and re-judged by the gate here -- e.g. the design page's OL10 `exit()` pine_adapter.cpp:8527 (main 8485; the merge had composed 13134). 3. By hand, each checked against the code it names: the floor citations `KERNEL_MIN_TESTS` ci_verify.py:274 and `RELEASE_MIN_TESTS` ci_verify.py:429 (the assignment lines; CONTRIBUTING.md and contributing-llm.md); design row E4's `PineScheduler::recalculate` pine_scheduler_native.cpp:636 and `coof_next_waypoint` pine_adapter.cpp:5742 (the row this lane merged by hand kept main's digits); design row CT9's `volume_weighted_cap` pine_adapter.cpp:2282-2338 (MAG-INTRABAR's own span, the retained lower-timeframe branch through the spec's validation, carried exactly from 9df16c24; main's 2281-2337 had drifted into cohort_for) and `deliver_confirmed_script` native_execution_consumer.cpp:7549-7815 (main's span carried exactly). Results on this tree: - check_doc_anchors.py: 1725 anchors, 1725 OK, 0 bad. - stale_scan.py against d0935605: 0 stale-carried anchors. - verify_carry.py over the same origins: 1707 EXACT, 9 EDITED (the six floor citations, whose cited assignment lines the floors item rewrote, and three design spans whose code a pick rewrote -- each passes the gate's claim), 9 NEW (prose the picks wrote). - check_doc_lint.py: no offenders. docs/build.sh: Doxygen warnings 0. - check_doc_reverts.py over d0935605..HEAD (20 commits), and in a checkout with no branch refs as on a lab remote host: 0 unnamed deletions or reverts. Co-Authored-By: Claude Opus 5.5 (1M context) <[email protected]> * INT27 (vi): the engine's merge-gate hook entry runs for MCP tool calls too, and blocks when it cannot start pineforge-workflow's docs/VERIFY.md ("Open decisions") records two gaps in the product repos' .claude/settings.json: the entry ran pr-gate.mjs for Bash only, so an MCP merge tool in an engine session met no hook, and without `|| exit 2` a hook that could not start (the file missing, a syntax error, node's own exit 1) let the call through, since Claude Code blocks only on exit 2. campaign/README.md's wiring closes both. The entry's matcher `Bash` becomes `Bash|mcp__.*`, and its pr-gate command gets `"timeout": 120` and a trailing `|| exit 2`, as the workflow repo's own entry has them. pr-gate.mjs reads only `tool_input.command`, so an MCP payload reaches it as an empty command and it answers "no opinion"; the same entry therefore also runs campaign/hooks/merge-gate.mjs (the file campaign/README.md wires for `mcp__.*`, with the same timeout and `|| exit 2`), which reads `tool_name` and `tool_input` and judges an MCP merge of an engine PR. On a Bash call it repeats the merge gate pr-gate.mjs runs first; both are deny-only. Checked through `sh -c` with the payload on stdin, as Claude Code runs a command hook: a benign Bash call and a benign MCP call exit 0 for both commands; with the hook file missing each exits 2. This is the last commit before the final lab remote: a session loads its project hooks at start, so the session that wrote this commit keeps running the previous entry. Co-Authored-By: Claude Opus 5.5 (1M context) <[email protected]> * Adapter: an exit limit the open's refill recalculation armed at the first extreme gap-fills there as a forced fill (R5 integration INT27, round 2: the gate sweep's regressed probe) INT27's gate sweep (exp-r5-int27-20260927, engine d3b753c1 + codegen a4259656, against rebaseline exp-rebaseline2b-20260926 on engine d0935605) refused the merge on one script, officialjackofalltrades-aureate-market-architecture-strategy-joat, on four lanes: OANDA:XAUUSD 15m (count +1), OANDA:EURUSD 15m (+3), BINANCE:BTCUSDT 15m (+7) and the scraped BINANCE:ETHUSDT.P lane (+4), every one excellent on the baseline. On XAUUSD the entry price moves from trade #60 on (3266.82 -> 3261.29). Bisect (the probe's own feeds and the pinned Lab verifier on spark, one library per pick boundary): 0631e045 (the INT27 merge fix) and c54f939e (PAR-ORDERS-3 findings 1-2) book the baseline trades (e8107dece428); e5efd189 -- PAR-ORDERS-3 finding 4, bc5f7a21: after the matcher's fill at a resting request's own level on a bar's first extreme, the recalculation's orders act from that extreme -- books 477b4cca24af, as every later commit. Mechanism, on the XAUUSD bar 2025-04-16 00:30 UTC (O 3261.715, H 3266.82, L 3261.29, C 3263.885, low first), traced in a scratch copy of the adapter: the strategy.exit limit leg carried from the previous bar (below the price) fills at the open; its recalculation re-enters, filled at the open too (the refill); that entry's recalculation re-places the exit, whose limit 3260.5585 is already through, so exit() arms it at the first extreme (later_same_open: StopLimit{W1 3261.29, 3260.5585}), where the path gap-fills it at 3261.29 -- TradingView's trade #59 exit. Its placement carries no forced_execution_price, so begin_coof_recalc left coof_fill_forced_ false, and finding 4's rule in coof_next_waypoint read the fill as the matcher's at the limit's own level ON the extreme: the market re-entry filled at W1, 3261.29. TradingView books it at the second extreme, 3266.82 (#60), as it books a market order after the control's forced fill (pa3-f4-point-w1-mkt-…
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Seven engine fixes from the TV-parity validation campaign:
7427720Enforce absolute count parity in corpus verifier —excellentnow requirescount_abs_delta == 0(percentage count thresholds demoted to display/strong-tier only)b3d2facFix equity sizing and POOC re-entry semantics2ba047eFix first-valid Pine cross edgesc467113Support Pine bar index offsetsa20ac1fNormalize TradingView GMT offsets for timezones56ab02fMaterialize relative exit ticks after entry fills222eb7dSupport unbiased stdev and varianceGates at HEAD:
ctest78/78 passed; corpus sweeprun_corpus.shran 252 ok=252 fail=0 (under the new strict verifier: excellent=228, strong=21, moderate=2, anomaly=1 — the stricter gate reclassifies, it does not regress runtime).🤖 Generated with Claude Code