feat(statistics): reconstruct a sequential e-process after a restart - #671
Merged
Conversation
drewstone
force-pushed
the
feat/sequential-gate-resume
branch
from
August 21, 2026 01:33
b93584b to
b390bd6
Compare
tangletools
approved these changes
Aug 21, 2026
tangletools
left a comment
Contributor
There was a problem hiding this comment.
✅ Auto-approved drewstone PR — b390bd66
This PR was opened by the trusted drewstone account.
This approval is provisional and was applied by the local stand-in because the pr-reviewer webhook host is unreachable (2026-08-21). CI on this head is fully green. The full PR reviewer audit re-runs via the resweep when the service returns and will publish findings if it detects issues.
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.
Why
#411 criterion 2 asks for proof that sequential state reconstructs after a process restart. It did not:
EProcessStatereported wealth and n but not the running sums the next bet is computed from, andeProcesshad no way to take a snapshot back, so a campaign that died mid-stream had to restart the test from n=0 — which is a fresh type-I budget on data that was already spent.What
EProcessStategainssumXandvarSum, the two running sums the plug-in bet reads (λ_iis a function ofx_1..x_{i-1}only, so the sums are exactly what a restart needs).eProcess({ resume })rebuilds a process from a snapshot. The snapshot never supplies the parameters:alpha,maxBet, andnullMeanresolve from the options as for a fresh process, and a snapshot recorded under different ones is refused with aValidationError— continuing a stream under new parameters after seeing the data reopens optional stopping.sequentialPairedGate({ resume })rebuilds the observe-stream from the newly exportedSequentialStreamState(the e-process state plus the gate decision).decide(ctx)is untouched: it always runs its own fresh stream.[0, n], a latch without itsdecidedAtN, an undecided snapshot already above the threshold, a gate decision this configuration could not have reached at that n (promotebelowminN,continueatmaxN,undecided-at-maxNat the wrong n).sequentialDecideneeds no snapshot — it is replayed from the generation history it is handed, and consumes each generation exactly once.Proof
The restart proof is
src/statistics/sequential-eprocess.test.tsand the new block insrc/campaign/gates/sequential.test.ts: a stream is interrupted at n = 0, 1, 4, 5, 7, 20, 30, 59, 119 and at the decision crossing, persisted throughJSON.parse(JSON.stringify(state())), rebuilt, and driven to the end — the wealth sequence, the observation sequence, the decision, and the final state are identical to the uninterrupted run, including a double restart and a manifest-bound stream.Full
pnpm testlocally: 5,330 passed, 12 files fail — the same 12 that fail on unmodifiedorigin/mainin this checkout (python-venv, subprocess, and git-worktree tests:benchmark-command*,gepa-*,skillopt-*,external-optimizer-process,worktree,product-benchmark/export). Verified by running that exact set on a cleanorigin/mainworktree: same 12 files, 58 failures. None touch statistics or the campaign gates. CI has the python toolchain and is the authority.Simplification: none — this is an irreducible addition. The two running sums already existed as closure state; the change publishes them on the snapshot instead of adding a parallel checkpoint path, so resume reuses the existing
state()shape rather than introducing a second one.Net: +596 / -16 lines, 12 files, 0 paths removed.
Tests: +2 files, 40 assertions covering restart identity and snapshot refusal (each prevents a resumed gate silently restarting its type-I budget or continuing under swapped parameters), -5 shape-only assertions dropped from the first draft (the type proves them).
Not done here:
sequentialDecidegets noresume— it reconstructs from history by design; a durable snapshot store for campaigns is a separate change.Refs #411 (criterion 2: restart reconstruction). Criteria 3 and 4 land in follow-up PRs.