The engine's Vest day now turns with the client's numbers, at the first
sync after the reset. A leg opened between 8 PM ET and that sync would be
planned and counted on the day that ended, so both the pick and the open
wait for it. The claim log's "stage N next" counts payouts the way the
engine picks its stage.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Two of the cycles a claim ends never got a completion entry. A Vest
day's second cycle is one: the auto-claim at the next tick beats the 30 s
report, and the payout books into that day's fund row, so the latest fund
date never moves for the catch-up. A cycle claimed right after the 20:00
ET reset is the other: the reset puts it back on stage 1, and all of its
P&L sits in the previous claim's day row, so endedCycleCompletion reads
none of it.
Before a claim goes out, claimedCycle (trading-logic) checks whether the
cycle stands complete: cycleCompletion 'today' or 'before' on the
client's numbers. It keys the cycle the way the final day would
(completionPlace on the payout list), so the master dedupes the two.
afterClaim keeps the result in account_meta. The reporter names each kept
cycle for the catch-up's week. It lists them last in the slice, newest
first, under the master's per-slice cap, and adds no counter.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
projectPerfectPath takes the raw trade date (default: the Central one):
the reporter passes its tradeDateFor day and the account page the one
/api/state now gives each account. From 5 PM CT to 20:00 ET it took
tomorrow as today while every input was Vest's, so the day's claim moved
a day late, the next day's stage-1 payout dropped, and an open Vest-day
row counted twice.
Without same-day stages, the stage comes from the client's payout list
(payoutDays, one per payout) when it has read one, not the negative fund
rows: Vest books a day's two claims as one row, so the engine, claimDue,
the stage label and the projection stayed a stage behind the report.
StageInputs.payouts carries the count; a client with no list counts rows
as before.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A sync whose positions read went out before the bot's own open or close
finished no longer writes that account's positions back (ownOrderSeq, as
claimSeq guards balances): the record a flatten goes by stays, so a read
lagging the fill still gives FLATTEN FAILED, not "nothing to flatten".
An open is noted in account_meta before its POST and dropped once its
outcome is known. After a restart the first sync takes the note up as an
open of unknown outcome, so the position it made is marked the bot's and
guardClose sees it. Such an open is matched by the position id its answer
named, else only to a position with no exit legs opened between the send
and a few seconds past the error (was two minutes): an outside
copy-trader's open half a minute on isn't taken for the bot's, and
several matches adopt none, loudly.
VestClient.tradeDate follows the last sync's numbers: past 8 PM ET the
day turns once a sync has worked out the fresh day's realized P&L, so
the engine, reporter and dashboard never pair the new day with the ended
day's numbers. A stalled sync holds the day back only while isClientReady
still trades on it.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The close gate held every Vest entry within four holds of any close,
which with a 2 h hold meant no weekday entry from about 9 AM to 5 PM ET
for the one-hour maintenance break. That hour reopens before the reset,
as CME's daily break does for futures legs, so only a weekend or holiday
closure gates an entry now.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The reporter and the dashboard take each firm's own trade date
(tradeDateFor), as the engine does: between 5 PM CT and Vest's 8 PM ET
reset the Central date counted the open Vest day as a prior day and as
today's P&L both, and could report a pass the master keeps for good. The
completion check's settle window now follows the client's own roll.
An open whose outcome came back unknown is marked the bot's once a read
shows the position it made, so the market-close guard closes it before a
long closure; an unmarked leg is no longer logged as a hand trade.
A symbol the close gate holds back stays on the candidate board for the
dashboard and the report, and fireLeg holds each account's leg to the
close at its own size, not just the batch lead's. check-vest-client.mjs
drives the guard and the board with every gateway call answered locally.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>