Repository navigation
Conversation
The coordinator waited up to 3,000 s for baseline and then up to a fresh 3,000 s for reform, so queued workers could push it past its own 4,500 s Modal timeout before it recorded the failure. Both waits now draw on one 3,000 s window, leaving 1,500 s for the 900 s production-result wait and 600 s of aggregation and failure persistence. When a child wait fails or times out, the coordinator now cancels every unfinished child, best effort, and records a cancelled sibling as failed, because Modal's InputCancellation is a BaseException the worker cannot record itself. Cancellation and state-update errors are logged and never replace the original child failure. This keeps the sequential baseline-then-reform wait; concurrent observation remains part of #712. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2 tasks done
Anchor the shared child-wait deadline when coordinate_report starts, so claiming, output planning, retained-artifact reads and dispatch shorten the children's waits rather than the 1,500 s left for the production-result wait, aggregation, persistence and failure recording. Add evaluation_id and the child's simulation_execution_id to the cancellation warnings, and cover finished siblings, restored calls and the ImmediateCall cancel double. The coordinator timeout test now runs the coordinator with simulated setup time against the declared Modal timeouts, so it lives beside the other coordinator tests. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2 tasks done
Contributor
Author
|
Closing this in favour of #712, which now covers #792 and lists |
anth-volk
added a commit
that referenced
this pull request
Oct 14, 2026
…eouts The coordinator stopped waiting 3,000 s after it started, although a US simulation worker may run for 3,900 s and each of its region-group calls for 3,600 s, so US simulations could never use the time Modal allowed them. The coordinator's 5,100 s timeout was not derived from either. Following the rule from #793, a new dependency-free stage12_timeouts module defines the worker timeouts, sets the shared child-wait window to the longest of them (3,900 s), and derives the coordinator's Modal timeout as that window plus the 900 s production-result wait plus 600 s to read results, aggregate, write artifacts and record the outcome: 5,400 s. A complete testing-environment US report took 288 s, so 600 s of finishing time is ample. The Modal app, coordinator and comparison step all read these constants. The last poll no longer sleeps past the deadline, so the window closes on time instead of up to 1 s late and the finishing time is not eroded. Tests read the declared Modal timeouts and check that the window covers every simulation worker's timeout and that the coordinator's timeout leaves the production wait plus at least 600 s. They also check that setup time shortens the window and that an exhausted window gives the children no extra time. Only the Modal timeout values change: no image, secret or environment variable attachment changes. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
anth-volk
added a commit
that referenced
this pull request
Oct 14, 2026
Adopt #793's cancellation practice in the concurrent coordinator: - Every simulation the coordinator stops, after a peer failure, a wait timeout or a coordinator failure, is recorded as failed with simulation_cancelled, and its error_summary gives the reason, for example "Cancelled after the baseline simulation failed.". The cancelled_after_peer_failure and cancelled_after_coordinator_failure codes and the incomplete status for cancellations are gone; the wait timeout stays the report's error code. - Only a running record changes, so a simulation that already succeeded or failed keeps its outcome. Workers already treat any status other than running as a cancellation, so a segmented worker still sees the failed record and cancels its own region-group calls. - An unsegmented simulation is always cancelled through Modal, even when its record could not be written. A segmented simulation is cancelled through Modal only when its record could not be written, because Modal does not cancel spawned calls recursively. Cancellation and state-update errors are still logged without replacing the original failure. Carry over #793's tests for a cancelled and recorded reform, a finished baseline left alone, a restored call cancelled on retry, finished siblings left unchanged, and both unfinished children cancelled on timeout. Add tests for the Modal fallback after a failed state write, for segmented and unsegmented simulations. ImmediateCall now counts cancellations, and the entry and persistence fixtures use the new cancellation record. Add a changelog line, as #793 did. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
anth-volk
added a commit
that referenced
this pull request
Oct 14, 2026
…eouts The coordinator stopped waiting 3,000 s after it started, although a US simulation worker may run for 3,900 s and each of its region-group calls for 3,600 s, so US simulations could never use the time Modal allowed them. The coordinator's 5,100 s timeout was not derived from either. Following the rule from #793, a new dependency-free stage12_timeouts module defines the worker timeouts, sets the shared child-wait window to the longest of them (3,900 s), and derives the coordinator's Modal timeout as that window plus the 900 s production-result wait plus 600 s to read results, aggregate, write artifacts and record the outcome: 5,400 s. A complete testing-environment US report took 288 s, so 600 s of finishing time is ample. The Modal app, coordinator and comparison step all read these constants. The last poll no longer sleeps past the deadline, so the window closes on time instead of up to 1 s late and the finishing time is not eroded. Tests read the declared Modal timeouts and check that the window covers every simulation worker's timeout and that the coordinator's timeout leaves the production wait plus at least 600 s. They also check that setup time shortens the window and that an exhausted window gives the children no extra time. Only the Modal timeout values change: no image, secret or environment variable attachment changes. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
anth-volk
added a commit
that referenced
this pull request
Oct 14, 2026
Adopt #793's cancellation practice in the concurrent coordinator: - Every simulation the coordinator stops, after a peer failure, a wait timeout or a coordinator failure, is recorded as failed with simulation_cancelled, and its error_summary gives the reason, for example "Cancelled after the baseline simulation failed.". The cancelled_after_peer_failure and cancelled_after_coordinator_failure codes and the incomplete status for cancellations are gone; the wait timeout stays the report's error code. - Only a running record changes, so a simulation that already succeeded or failed keeps its outcome. Workers already treat any status other than running as a cancellation, so a segmented worker still sees the failed record and cancels its own region-group calls. - An unsegmented simulation is always cancelled through Modal, even when its record could not be written. A segmented simulation is cancelled through Modal only when its record could not be written, because Modal does not cancel spawned calls recursively. Cancellation and state-update errors are still logged without replacing the original failure. Carry over #793's tests for a cancelled and recorded reform, a finished baseline left alone, a restored call cancelled on retry, finished siblings left unchanged, and both unfinished children cancelled on timeout. Add tests for the Modal fallback after a failed state write, for segmented and unsegmented simulations. ImmediateCall now counts cancellations, and the entry and persistence fixtures use the new cancellation record. Add a changelog line, as #793 did. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
anth-volk
added a commit
that referenced
this pull request
Oct 14, 2026
…eouts The coordinator stopped waiting 3,000 s after it started, although a US simulation worker may run for 3,900 s and each of its region-group calls for 3,600 s, so US simulations could never use the time Modal allowed them. The coordinator's 5,100 s timeout was not derived from either. Following the rule from #793, a new dependency-free stage12_timeouts module defines the worker timeouts, sets the shared child-wait window to the longest of them (3,900 s), and derives the coordinator's Modal timeout as that window plus the 900 s production-result wait plus 600 s to read results, aggregate, write artifacts and record the outcome: 5,400 s. A complete testing-environment US report took 288 s, so 600 s of finishing time is ample. The Modal app, coordinator and comparison step all read these constants. The last poll no longer sleeps past the deadline, so the window closes on time instead of up to 1 s late and the finishing time is not eroded. Tests read the declared Modal timeouts and check that the window covers every simulation worker's timeout and that the coordinator's timeout leaves the production wait plus at least 600 s. They also check that setup time shortens the window and that an exhausted window gives the children no extra time. Only the Modal timeout values change: no image, secret or environment variable attachment changes. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
anth-volk
added a commit
that referenced
this pull request
Oct 14, 2026
Adopt #793's cancellation practice in the concurrent coordinator: - Every simulation the coordinator stops, after a peer failure, a wait timeout or a coordinator failure, is recorded as failed with simulation_cancelled, and its error_summary gives the reason, for example "Cancelled after the baseline simulation failed.". The cancelled_after_peer_failure and cancelled_after_coordinator_failure codes and the incomplete status for cancellations are gone; the wait timeout stays the report's error code. - Only a running record changes, so a simulation that already succeeded or failed keeps its outcome. Workers already treat any status other than running as a cancellation, so a segmented worker still sees the failed record and cancels its own region-group calls. - An unsegmented simulation is always cancelled through Modal, even when its record could not be written. A segmented simulation is cancelled through Modal only when its record could not be written, because Modal does not cancel spawned calls recursively. Cancellation and state-update errors are still logged without replacing the original failure. Carry over #793's tests for a cancelled and recorded reform, a finished baseline left alone, a restored call cancelled on retry, finished siblings left unchanged, and both unfinished children cancelled on timeout. Add tests for the Modal fallback after a failed state write, for segmented and unsegmented simulations. ImmediateCall now counts cancellations, and the entry and persistence fixtures use the new cancellation record. Add a changelog line, as #793 did. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
anth-volk
added a commit
that referenced
this pull request
Oct 14, 2026
…eouts The coordinator stopped waiting 3,000 s after it started, although a US simulation worker may run for 3,900 s and each of its region-group calls for 3,600 s, so US simulations could never use the time Modal allowed them. The coordinator's 5,100 s timeout was not derived from either. Following the rule from #793, a new dependency-free stage12_timeouts module defines the worker timeouts, sets the shared child-wait window to the longest of them (3,900 s), and derives the coordinator's Modal timeout as that window plus the 900 s production-result wait plus 600 s to read results, aggregate, write artifacts and record the outcome: 5,400 s. A complete testing-environment US report took 288 s, so 600 s of finishing time is ample. The Modal app, coordinator and comparison step all read these constants. The last poll no longer sleeps past the deadline, so the window closes on time instead of up to 1 s late and the finishing time is not eroded. Tests read the declared Modal timeouts and check that the window covers every simulation worker's timeout and that the coordinator's timeout leaves the production wait plus at least 600 s. They also check that setup time shortens the window and that an exhausted window gives the children no extra time. Only the Modal timeout values change: no image, secret or environment variable attachment changes. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
anth-volk
added a commit
that referenced
this pull request
Oct 14, 2026
Adopt #793's cancellation practice in the concurrent coordinator: - Every simulation the coordinator stops, after a peer failure, a wait timeout or a coordinator failure, is recorded as failed with simulation_cancelled, and its error_summary gives the reason, for example "Cancelled after the baseline simulation failed.". The cancelled_after_peer_failure and cancelled_after_coordinator_failure codes and the incomplete status for cancellations are gone; the wait timeout stays the report's error code. - Only a running record changes, so a simulation that already succeeded or failed keeps its outcome. Workers already treat any status other than running as a cancellation, so a segmented worker still sees the failed record and cancels its own region-group calls. - An unsegmented simulation is always cancelled through Modal, even when its record could not be written. A segmented simulation is cancelled through Modal only when its record could not be written, because Modal does not cancel spawned calls recursively. Cancellation and state-update errors are still logged without replacing the original failure. Carry over #793's tests for a cancelled and recorded reform, a finished baseline left alone, a restored call cancelled on retry, finished siblings left unchanged, and both unfinished children cancelled on timeout. Add tests for the Modal fallback after a failed state write, for segmented and unsegmented simulations. ImmediateCall now counts cancellations, and the entry and persistence fixtures use the new cancellation record. Add a changelog line, as #793 did. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
anth-volk
added a commit
that referenced
this pull request
Oct 14, 2026
…eouts The coordinator stopped waiting 3,000 s after it started, although a US simulation worker may run for 3,900 s and each of its region-group calls for 3,600 s, so US simulations could never use the time Modal allowed them. The coordinator's 5,100 s timeout was not derived from either. Following the rule from #793, a new dependency-free stage12_timeouts module defines the worker timeouts, sets the shared child-wait window to the longest of them (3,900 s), and derives the coordinator's Modal timeout as that window plus the 900 s production-result wait plus 600 s to read results, aggregate, write artifacts and record the outcome: 5,400 s. A complete testing-environment US report took 288 s, so 600 s of finishing time is ample. The Modal app, coordinator and comparison step all read these constants. The last poll no longer sleeps past the deadline, so the window closes on time instead of up to 1 s late and the finishing time is not eroded. Tests read the declared Modal timeouts and check that the window covers every simulation worker's timeout and that the coordinator's timeout leaves the production wait plus at least 600 s. They also check that setup time shortens the window and that an exhausted window gives the children no extra time. Only the Modal timeout values change: no image, secret or environment variable attachment changes. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
anth-volk
added a commit
that referenced
this pull request
Oct 14, 2026
Adopt #793's cancellation practice in the concurrent coordinator: - Every simulation the coordinator stops, after a peer failure, a wait timeout or a coordinator failure, is recorded as failed with simulation_cancelled, and its error_summary gives the reason, for example "Cancelled after the baseline simulation failed.". The cancelled_after_peer_failure and cancelled_after_coordinator_failure codes and the incomplete status for cancellations are gone; the wait timeout stays the report's error code. - Only a running record changes, so a simulation that already succeeded or failed keeps its outcome. Workers already treat any status other than running as a cancellation, so a segmented worker still sees the failed record and cancels its own region-group calls. - An unsegmented simulation is always cancelled through Modal, even when its record could not be written. A segmented simulation is cancelled through Modal only when its record could not be written, because Modal does not cancel spawned calls recursively. Cancellation and state-update errors are still logged without replacing the original failure. Carry over #793's tests for a cancelled and recorded reform, a finished baseline left alone, a restored call cancelled on retry, finished siblings left unchanged, and both unfinished children cancelled on timeout. Add tests for the Modal fallback after a failed state write, for segmented and unsegmented simulations. ImmediateCall now counts cancellations, and the entry and persistence fixtures use the new cancellation record. Add a changelog line, as #793 did. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
anth-volk
added a commit
that referenced
this pull request
Oct 14, 2026
…eouts The coordinator stopped waiting 3,000 s after it started, although a US simulation worker may run for 3,900 s and each of its region-group calls for 3,600 s, so US simulations could never use the time Modal allowed them. The coordinator's 5,100 s timeout was not derived from either. Following the rule from #793, a new dependency-free stage12_timeouts module defines the worker timeouts, sets the shared child-wait window to the longest of them (3,900 s), and derives the coordinator's Modal timeout as that window plus the 900 s production-result wait plus 600 s to read results, aggregate, write artifacts and record the outcome: 5,400 s. A complete testing-environment US report took 288 s, so 600 s of finishing time is ample. The Modal app, coordinator and comparison step all read these constants. The last poll no longer sleeps past the deadline, so the window closes on time instead of up to 1 s late and the finishing time is not eroded. Tests read the declared Modal timeouts and check that the window covers every simulation worker's timeout and that the coordinator's timeout leaves the production wait plus at least 600 s. They also check that setup time shortens the window and that an exhausted window gives the children no extra time. Only the Modal timeout values change: no image, secret or environment variable attachment changes. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
anth-volk
added a commit
that referenced
this pull request
Oct 14, 2026
Adopt #793's cancellation practice in the concurrent coordinator: - Every simulation the coordinator stops, after a peer failure, a wait timeout or a coordinator failure, is recorded as failed with simulation_cancelled, and its error_summary gives the reason, for example "Cancelled after the baseline simulation failed.". The cancelled_after_peer_failure and cancelled_after_coordinator_failure codes and the incomplete status for cancellations are gone; the wait timeout stays the report's error code. - Only a running record changes, so a simulation that already succeeded or failed keeps its outcome. Workers already treat any status other than running as a cancellation, so a segmented worker still sees the failed record and cancels its own region-group calls. - An unsegmented simulation is always cancelled through Modal, even when its record could not be written. A segmented simulation is cancelled through Modal only when its record could not be written, because Modal does not cancel spawned calls recursively. Cancellation and state-update errors are still logged without replacing the original failure. Carry over #793's tests for a cancelled and recorded reform, a finished baseline left alone, a restored call cancelled on retry, finished siblings left unchanged, and both unfinished children cancelled on timeout. Add tests for the Modal fallback after a failed state write, for segmented and unsegmented simulations. ImmediateCall now counts cancellations, and the entry and persistence fixtures use the new cancellation record. Add a changelog line, as #793 did. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
anth-volk
added a commit
that referenced
this pull request
Oct 19, 2026
* Add Stage 12 segmentation foundations * Add Stage 12 segment calculation and merge * Add Stage 12 cache identity and loading * Add Stage 12 cache precompute app * Bake Stage 12 caches into US workers * Fan out Stage 12 US simulations * Qualify and document Stage 12 execution * Fix Stage 12 precompute image sources * Validate Stage 12 cache deploy access * Keep Stage 12 deployment validation independent * Validate Stage 12 reform intervals * Preserve Stage 12 failure details * Observe Stage 12 simulations concurrently * Document Stage 12 failure handling * Reconcile segmented Stage 12 execution with current typed provenance * Identify the report and child in Stage 12 cancellation logs Cancellation state-update and cancel-request failures previously logged only the simulation role and error type. They now also log the report's evaluation_id and the child's simulation_execution_id, in the message and as record attributes, and still omit the error's own message. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Stop started Stage 12 workers when coordinator startup fails Only a failed spawn used to cancel already-started children. Any other coordinator failure after the first spawn, such as a failed dispatch placeholder write, a failed invocation attach, a failed restore, or a retained-artifact error, reached the report failure handler, which marked the report failed but left every started worker running until its own timeout. The handler now stops every started, unfinished child with the existing cancellation path: it records the child as incomplete with cancelled_after_coordinator_failure, cancels an unsegmented call, and lets a segmented call stop itself once it reads that record. Children that already finished are left unchanged. Child, dispatch and wait-timeout failures keep their own peer cancellation, and cancellation or state-update errors are logged without replacing the original failure. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Open the Stage 12 child wait window at coordinator entry The child-wait deadline used to start when observation began, after claiming, output planning (including the country model load), retained-artifact reads and dispatch. Setup time therefore came out of the coordinator's remaining Modal time rather than the children's window. The 3,000 s window now opens when coordinate_report starts, so setup shortens the children's window and the coordinator always keeps 2,100 s of its 5,100 s Modal timeout after the window: up to 900 s for the production-result wait and 1,200 s to read results, aggregate, write artifacts and record the outcome. The timeout summary now says the window is measured from the coordinator's start. A new test runs the coordinator with 0, 400 and 2,000 s of simulated setup, checks that the window closes 3,000 s after entry, and checks the declared Modal timeouts still leave the production wait plus at least 600 s. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Size the Stage 12 wait window and coordinator timeout from worker timeouts The coordinator stopped waiting 3,000 s after it started, although a US simulation worker may run for 3,900 s and each of its region-group calls for 3,600 s, so US simulations could never use the time Modal allowed them. The coordinator's 5,100 s timeout was not derived from either. Following the rule from #793, a new dependency-free stage12_timeouts module defines the worker timeouts, sets the shared child-wait window to the longest of them (3,900 s), and derives the coordinator's Modal timeout as that window plus the 900 s production-result wait plus 600 s to read results, aggregate, write artifacts and record the outcome: 5,400 s. A complete testing-environment US report took 288 s, so 600 s of finishing time is ample. The Modal app, coordinator and comparison step all read these constants. The last poll no longer sleeps past the deadline, so the window closes on time instead of up to 1 s late and the finishing time is not eroded. Tests read the declared Modal timeouts and check that the window covers every simulation worker's timeout and that the coordinator's timeout leaves the production wait plus at least 600 s. They also check that setup time shortens the window and that an exhausted window gives the children no extra time. Only the Modal timeout values change: no image, secret or environment variable attachment changes. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Record cancelled Stage 12 simulations as failed and always stop them Adopt #793's cancellation practice in the concurrent coordinator: - Every simulation the coordinator stops, after a peer failure, a wait timeout or a coordinator failure, is recorded as failed with simulation_cancelled, and its error_summary gives the reason, for example "Cancelled after the baseline simulation failed.". The cancelled_after_peer_failure and cancelled_after_coordinator_failure codes and the incomplete status for cancellations are gone; the wait timeout stays the report's error code. - Only a running record changes, so a simulation that already succeeded or failed keeps its outcome. Workers already treat any status other than running as a cancellation, so a segmented worker still sees the failed record and cancels its own region-group calls. - An unsegmented simulation is always cancelled through Modal, even when its record could not be written. A segmented simulation is cancelled through Modal only when its record could not be written, because Modal does not cancel spawned calls recursively. Cancellation and state-update errors are still logged without replacing the original failure. Carry over #793's tests for a cancelled and recorded reform, a finished baseline left alone, a restored call cancelled on retry, finished siblings left unchanged, and both unfinished children cancelled on timeout. Add tests for the Modal fallback after a failed state write, for segmented and unsegmented simulations. ImmediateCall now counts cancellations, and the entry and persistence fixtures use the new cancellation record. Add a changelog line, as #793 did. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Test that a closed Stage 12 wait window is reported first The rebase onto #789 reports a closed child-wait window to telemetry before cancellation and report failure records are written, as every other Stage 12 failure is. This test makes those writes fail and checks that the timeout still reached telemetry first. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Keep a failed Stage 12 child's failure when its own record errors The coordinator read a failed child's record, to choose its failure detail, outside any guard. One database error on that read reached the report handler: the report was recorded as report_coordination_failed, and the failed child and its peer were both recorded as cancelled "after the coordinator failed". Reading and writing the failed child's own record, in both the child-wait and the dispatch-failure paths, is now non-fatal in the same way as the cancellation writes. The error is logged with the report and simulation identifiers and its type, but not its message. The report keeps the child's failure as its code and cause, the failed child is recorded as failed with its own cause where the record can still be written and is never recorded as cancelled, and its peers are cancelled "after the <role> simulation failed". Each failure is now also reported once. The coordinator, the simulation worker and the segment fan-out reported an unexpected error both through the original-failure report and again through the correlation-ID log. One report now carries the correlation ID that the redacted summary persists, with the report and simulation identifiers. A segment failure is reported where it occurs, and the worker does not report it again. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Mount only the read-only Hugging Face secret in the Stage 12 precompute app The Stage 12 cache precompute app, which runs on every Stage 12 deployment, mounted the retiring policyengine-data-credentials and huggingface-token (HF_TOKEN) Modal secrets on its image build and all five functions. The credential runbook removes both from simulation code. Its image build and functions now mount pe-uk-private-hf-read-token, which supplies HUGGING_FACE_TOKEN, declared through the same constants and required key as the executor and v2 apps. The US data the app reads comes only from the public policyengine/populace-us dataset repository, which the v2 US worker image already downloads with this token. The guard test that keeps the retired names out of deployment sources now covers this app. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Register the Stage 12-only integration test in the rules registry The rules registry guard that landed on main with #752 requires every deployment-asset guard test to belong to a rule. Add the test that keeps the Stage 12-only deploy from running the existing stack's complete integration suite to sim.stage12.deployment-scope, widen the statement to say so, and re-render the rules page and the AGENTS.md block. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Return valid aggregates from the Stage 12 test aggregators #787 made the coordinator tests' artifact double write aggregates through the real Stage12ArtifactStore, which rejects anything that is not a valid AggregateReportArtifactPayload. Use _aggregate_payload for this PR's aggregator stubs that must not run, as #787 did for main's, so an unexpected run shows up as a written aggregate instead of as a rejection hidden by the failure the test expects. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Keep the v2 manifest readable by readers released before the cache The manifest models forbid unknown fields, so readers already deployed reject a manifest carrying the new cache release fields, and a cold reader then has no valid manifest. The manifest is published before the reading revision is promoted, staging deploys never promote, and a rollback or revert would read the same document. The publisher now writes the manifest under the active-with-cache key and the same manifest without cache releases under the existing active key. Current readers read active-with-cache, falling back to active only before the first publish that writes both. A test pins the fields earlier readers accept. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Fix Stage 12 cache file names, forced rebuilds and the determinism gate Name each baseline file as .py's Simulation.storage_id names the file it saves and loads. A US simulation always resolves an SPM selection, so .py appends its digest; the cache used the bare simulation ID, so precompute never found the file it had calculated and no worker could load a baked one. The identity now holds the resolved selection the worker builds the simulation with, and a test compares the planned name with the real worker model's. Remove force from the Stage 12 cache. Stored files are immutable and create-only, and HDF5 baselines are not byte-reproducible, so v1's force_recompute input made every forced run fail. Record a passing determinism check in the cache bucket and publish the manifest only when that record exists. Previously a run that computed no baselines skipped the check, so running again after a failure published baselines that had failed it. The check now also requires the stored baseline to load as a cache hit. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Remove the Stage 12 ruff suppressions the main merge added Fix the findings instead of suppressing them; only deliberate catch-all handlers keep a suppression, each with its reason. - Import at module level everywhere the deferred imports had no real need: the precompute app, the image-build download, the cache build, worker validation, qualification, segment fan-out and the v2 app. Modules that tests patch are imported whole and called through. - Break the two import cycles. Stage12CachedSimulation moves from stage12_cache.runtime to stage12_runtime.cached_simulation, and should_segment_simulation moves into the partition module, so the simulation module imports both at module level. The stage12_cache package no longer imports .py. - When a stored baseline fails its output plan, clear .py's in-memory cache with its public clear() instead of replacing one private entry. The next ensure loads the saved file. - Annotate the precompute's Modal handles as modal.Function and drop the duplicated RemoteFunction protocol, and type the fan-out's Modal module. - Move two raises out of try blocks into helpers, and raise TypeError for the image build's two manifest type checks. - Give the six catch-all suppressions this PR already had their reasons. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Install only US data in the Stage 12 cache precompute image The precompute image ran `policyengine bundle install` with --venv, which asks .py to pip-install the bundle's packages into the uv environment. That environment has no pip, so with .py 6.7.5 the image build failed with "No module named pip" in the first testing deploy. The locked modal-simulation-image group already installs .py and the country packages, so the image now installs only the US data through bundle_data_install_command, as the v2 worker images do. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> --------- Co-authored-by: Anthony Volk <14987227+anth-volk@users.noreply.github.com> Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
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.
Fixes #792
Same-Repository Draft PR Check
PolicyEngine/policyengine-sim-api, not a personal fork.Summary
This is an interim change before #712. It keeps the sequential baseline-then-reform wait, but bounds it and cleans up after a failure.
SIMULATION_WAIT_TIMEOUT_SECONDS, the same as the workers' Modal timeout) opens whencoordinate_reportstarts. It covers coordinator setup (claiming, output planning including the country model load, retained-artifact reads and dispatch) and both child waits. Eachcall.getreceives only the remaining time, never less than zero.coordinate_reportinv2_app.py._cancel_unfinished_childrencancels every unfinished child, best effort. This includes a timed-out child that is still running, and a call restored from an earlier coordinator attempt.RUNNINGasFAILEDwitherror_code="simulation_cancelled". A sibling that has already recordedSUCCEEDEDorFAILEDis left unchanged. Modal'sInputCancellationis aBaseException, so the worker can't record its own outcome.stage12_child_cancel_failed,stage12_cancelled_child_state_update_failed) carryevaluation_id, the child'ssimulation_execution_id,simulation_roleanderror_type, but no error message.ChildCallgainscancel(). Modal'sFunctionCall.cancelalready exists.Interaction with other PRs
_cancel_unfinished_children;coordinate_reportstarts, not when polling starts, to keep the guaranteed 1,500 s;cancel()line todependencies.py;cancel()doubles totests/test_stage12_runtime.py.Testing
New tests in
tests/test_stage12_runtime.py:SUCCEEDEDorFAILEDunchanged.Suites, on Python 3.13 with
uv run --frozen:Regression checks: I reverted each behaviour in turn. Each time, the matching new test failed:
RUNNINGcheck fails both finished-sibling tests;The original cancellation tests still fail against the code before this PR only at their clock fixture, because they need the new monotonic-clock hook.
Formatting and lint:
ruff format --checkandgit diff --checkpass.ruff checkwith the locked ruff (0.15.11) is clean on the changed files.tests/test_stage12_runtime.py, and the same four are already onmain.Not run: Pyright, which isn't installed in the test environment.
🤖 Generated with Claude Code