Repository navigation
Conversation
anth-volk
force-pushed
the
feat/stage12-segmentation-cache
branch
2 times, most recently
from
October 1, 2026 12:30
d5f6837 to
16c7701
Compare
anth-volk
force-pushed
the
feat/stage12-segmentation-cache
branch
from
October 12, 2026 12:32
16c7701 to
069ec46
Compare
This was referenced Oct 13, 2026
anth-volk
force-pushed
the
feat/stage12-segmentation-cache
branch
4 times, most recently
from
October 14, 2026 20:24
f22d344 to
f510ed9
Compare
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>
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>
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>
…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>
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>
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>
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>
…te 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>
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>
#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>
anth-volk
force-pushed
the
feat/stage12-segmentation-cache
branch
from
October 14, 2026 21:58
f510ed9 to
0cc170d
Compare
#791 records a redacted Stage 12 failure cause (type, stage, simulation role and message) where this branch persisted a generic message with a correlation ID for every unexpected error. Keep this branch's failure model (typed failures, preserved worker causes, cancellation of unfinished simulations, exactly-once reports) and use #791's cause in it: - redacted_failure_detail summarises an unexpected error with failure_summary, followed by its correlation ID. The cause is shortened, never the ID, to fit the 512-character summary. Typed, propagated and cancellation failures are unchanged. - The coordinator and workers open their spans and operations through tracked_stage, so a failure names its stage. The coordinator's concurrent wait records each child's role while probing it. - The coordinator and workers attach the redacted cause, with the original stack, to the failing operation before writing the failure record. The original error is still reported once. - Tests expect the new summaries, and #791's cause tests are ported with this branch's error codes. The README and the Stage 12 migration notes describe the new summary. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This branch has not been deployed
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 #711
Fixes #792
Same-repository draft PR check
PolicyEngine/policyengine-sim-api, not a personal fork.Summary
persist_failure_record.pe-uk-private-hf-read-tokenHugging Face secret. See "Fixes after review" below.Fixes after review
A failed simulation's own state error no longer replaces its failure (
b6c691d1)Before this fix, the coordinator read a failed child's record, to choose its failure detail, outside any guard. A reproduction in which one database read of the failed baseline's record fails recorded the report as
report_coordination_failedinstead ofsimulation_invocation_failed, recorded the failed baseline itself assimulation_cancelled("Cancelled after the coordinator failed."), and gave the reform the same wrong reason. A failing write of that record was already caught, but it was logged without the report or simulation identifiers.evaluation_id,simulation_execution_id, the role and the error type, in the message and as record attributes. The error's message is not logged.simulation_invocation_failedorsimulation_dispatch_failed, or the typed failure the worker recorded).simulation_cancelled, and it is not cancelled through Modal.Each failure is reported once
#789's contract is that each failure is reported once. After the rebase, an unexpected error reached telemetry twice: once through #789's
report_original_failure("Stage 12 execution failed", with the error), and again through this PR'sfailure_detail_from_exception, which calledlog_and_redact_exception. That second report was a standard-library ERROR log with the stack trace,runtime.record_exceptionand agateway_error_redactedevent. It happened in the worker, child-wait, child-dispatch and report-coordination handlers. A segmented simulation's failure was also reported twice: the fan-out logged the segment error, and the worker then reported the wrappingStage12ExecutionError.report_failurehelper builds the redacted detail without logging it and emits onereport_original_failurerecord. That record carries the samecorrelation_idas the persistedSimulation failed (correlation_id=...)summary, plusevaluation_idand, for a simulation,simulation_execution_idand the role. Without a runtime, the one standard-library log line includes the correlation ID.failure_detail_from_exceptionis replaced byredacted_failure_detail, which only describes a failure and never reports it.The Stage 12 precompute app mounts only the read-only Hugging Face secret (
eef03c3c)src/modal/stage12_precompute_app.pyruns on every Stage 12 deployment. It mounted the retiringpolicyengine-data-credentialsandhuggingface-token(required_keys=["HF_TOKEN"]) Modal secrets on its image build and all five functions.policyengine bundle install ... --country us) and all five functions now mountpe-uk-private-hf-read-tokenwithrequired_keys=["HUGGING_FACE_TOKEN"]. The secret is declared through the sameHF_MODAL_SECRET_NAMEandHF_RUNTIME_ENV_NAMEconstants asapp.pyandv2_app.py. The functions keepstage12-evaluation-gcp-credentials. The app never readHF_TOKENitself, and nothing else changes.hf://policyengine/populace-us/.... This covers the bundle install in the image build and any dataset materialization duringensure_datasetsor a calculation. PolicyEngine 6.3.4's runtime code names no other Hugging Face repository for the US.policyengine/populace-usis a public, ungated dataset repository. The token's scope covers only the two private UK repositories, and this public repository needs no grant. The same token already downloads these artifacts in the v2 US worker image build. That layer was rebuilt with only this secret in today's 6.3.4 deployment (run 38545891000, staging) and installedpopulace_us_2024.h5frompolicyengine/populace-us. No credential was widened.test_deployment_sources_exclude_legacy_hf_secret_namesnow includes this app. A new declaration test checks the secret on the image build and every function. Both fail on the previous app source.Environment variables and wiring
HUGGING_FACE_TOKENPE_UK_PRIVATE_HF_READ_TOKEN, copied into Modal secretpe-uk-private-hf-read-tokenpreparejob validates the GitHub value, then runsmodal secret create pe-uk-private-hf-read-token HUGGING_FACE_TOKEN=... --env=<modal_environment> --forcewhendeploy_existing_stackordeploy_stage12_v2is true.deploy_stage12_v2needs: prepare, and its implicitsuccess()condition means the sync has succeeded, in the same Modal environment, before "Build the independent Stage 12 cache" runs. The sync is in thepreparejob, not in the same job as the precompute step. The app attaches the secret to the image build and every function.GOOGLE_APPLICATION_CREDENTIALS_JSONvars.STAGE12_GCP_CREDENTIALS_SECRET_NAME, copied into Modal secretstage12-evaluation-gcp-credentialsstage12-sync-modal-secrets.sh, in the samedeploy_stage12_v2job, runs before the precompute step.POLICYENGINE_DATA_FOLDERSTAGE12_CACHE_BUCKETvars.STAGE12_CACHE_BUCKETenv:.MODAL_TOKEN_ID,MODAL_TOKEN_SECRETmodal secret createandmodal runenv:.release_environment: beta, Modalstaging) and production (prod, Modalmain) call the reusable workflow withdeploy_stage12_v2: trueandsecrets: inherit, from bothsimulation-deploy.ymlandstage12-deploy.yml.modal secret listshowedpe-uk-private-hf-read-tokenandstage12-evaluation-gcp-credentialsin bothstagingandmain, each used on 2026-10-14. Secret values and the GitHub secret were not inspected.PE_UK_PRIVATE_HF_READ_TOKENis granted to this repository and is valid. Today's successful deployments, which validate and synchronize it, indicate that it is. The precompute app has not run with the new secret, because no deployment was run.Rebased onto main after #789
The branch is rebased onto
5484278455e7fd48bb8d874f0e26245895d2730c, the merge of #789. The earlier merge commit from main is gone, and each commit of this PR now builds on #789.Connection opener
Stage12PersistenceStore.replace_simulation_if_status, which this PR adds, opens its connection through_transaction, like every other store operation. Only the connect step can be retried; its statements and commit are never retried.runtime_store(runtime), so a refused connection is retried and each retry is logged with the operation name. The Cloud Run entrypoint keeps the non-retrying default.Failure recording
report_original_failure, before any database write. This covers worker failures, segment failures, child dispatch failures, child failures seen while observing, and report failures. See "Fixes after review" for how the report now carries the correlation ID.persist_failure_record, which logs a failed write instead of raising it. A failed simulation's own record is updated by the coordinator through_record_child_failure, which logs a failed read or write with the report and simulation identifiers, like the cancellation records.replace_simulation_if_statuswrites.Stage12ExecutionErrorafter being reported where they occur. The report handler therefore reports only other errors, so each failure is reported once.child_wait_timeout, before the cancellation records and the report record are written. A new test makes those writes fail and checks that the report still reached telemetry first._mark_child_failedis folded into this PR's_replace_running_simulation, which the dispatch, child-failure and cancellation paths share. It only changes a running record, which this PR requires.evaluation_idandsimulation_execution_id, and an unfinished child is then cancelled through Modal. They do not usepersist_failure_record, because the coordinator must know whether the record was written.Known open issue (fixed after review)
The coordinator read a failed child's record outside the failure-recording guard, so an error on that read replaced the child's failure. This is fixed in
b6c691d1; see "Fixes after review". #789's test for this case,test_coordinator_reports_a_child_failure_once_when_its_record_is_unwritable, is no longer markedxfailand passes.Connection retries and the finishing time
#789 retries a refused connection for up to 60 s. The last attempt can start just before 60 s and then wait up to the 10 s connect timeout, so one store operation can take about 70 s when the pooler refuses throughout. After the wait window closes:
If the coordinator ever exceeded 5,400 s, Modal would stop it and the report would stay running without a failure record. The timeouts are unchanged in this rebase.
Replaces #793 and covers #792
This PR replaces #793 and adopts its practices. Issue #792 asks for one shared wait deadline that fits inside the coordinator's timeout, and for every unfinished worker to be cancelled and recorded as failed. Observing baseline and reform concurrently was always part of this PR.
Wait window and timeouts
This PR follows #793's rule: the shared wait equals the workers' Modal timeout, and the coordinator's timeout is that wait plus 900 s for the production-result wait plus 600 s to finish.
coordinate_reportstarts. It covers claiming, output planning (including loading the country model), retained-artifact reads, dispatch, and the concurrent wait for both simulations. Setup time therefore shortens the simulations' window, not the time the coordinator needs afterwards.PRODUCTION_RESULT_WAIT_TIMEOUT_SECONDS);stage12_timeouts.py, defines the worker timeouts, the window and the finishing time, and derives the coordinator timeout from them. The Modal app declaration, the coordinator and the comparison step all read it.timeoutvalues ofrun_single_simulation_us,run_single_simulation_ukandcoordinate_reportchange. Their images,worker_secrets(the GCP, Hugging Face and comparison-runtime Modal secrets) and environment are unchanged. The new constants module ships in the existingpolicyengine_simulation_executorpackage source that every Stage 12 image already includes. No CI, Docker or Terraform changes.Cancellation
Recorded as failed. Every simulation the coordinator cancels is recorded as
failedwithsimulation_cancelled. Itserror_summarygives the reason:simulation_wait_timeout;The earlier
incompletestatus and thecancelled_after_peer_failureandcancelled_after_coordinator_failurecodes are gone. Nothing else needed them: workers treat any status other thanrunningas a cancellation, and the entry service passes statuses and codes through unchanged.Only running records change. A simulation that has already succeeded or failed keeps its own outcome.
Always stopped in Modal. An unsegmented simulation is always cancelled through Modal, even if its record could not be written. A segmented simulation reads its failed record, cancels its own region-group calls and exits. Modal does not cancel spawned calls recursively, so the coordinator cancels a segmented simulation through Modal only if it could not write the record.
Startup failures too. Any coordinator failure after the first spawn stops every started, unfinished simulation. Examples are a failed dispatch placeholder write, a failed invocation attach (including the simulation whose attach failed), a failed restore and a retained-artifact error. A call restored from an earlier coordinator attempt is stopped too. Before this update, only a failed spawn did this.
Errors never mask the original failure. Cancellation and state-update errors, including errors reading or writing the failed simulation's own record, are logged, and the report keeps the original failure.
Traceable logs. When recording or requesting a cancellation fails, the log includes
evaluation_idand the simulation'ssimulation_execution_id, in the message and as record attributes, alongside the role and error type. The error message itself is not logged. Share one Stage 12 child wait deadline and cancel unfinished children #793 used event-name messages with these fields only as attributes. This PR also puts them in the message, because the observability log handler exports only the message.Carried over from #793
fixtures.fake_modal, and the setup-time and exhausted-window tests.simulation_cancelledfailed records, the running-only guard, and Modal cancellation even when the state write fails.ImmediateCall.cancelnow counts cancellations.changelog_entry.yamlkeeps Release Stage 12 database sessions and keep original failures visible #789's line and this PR's line.call.gettimeouts, because this PR polls both simulations without blocking.Validation of the review fixes
uv sync --extra testenvironment: 1149 passed, 22 skipped, 3 deselected, 0 xfailed (was 1134 passed and 1 xfailed).tests/test_stage12_*.py): 213 passed.test_coordinator_reports_a_child_failure_once_when_its_record_is_unwritableno longer has itsxfailmarker and passes. Its expected report attributes now include the identifiers and the correlation ID.format --checkandcheckon the 10 changed Python files: clean. Ruffformat --checkon everyprojects/*/srcandlibs/*/srcdirectory: clean.git diff --check: clean.Merged main after #791
#791 stores a redacted failure cause: the type, the stage, the simulation role and the message. For every unexpected error, this PR stored a generic message with a correlation ID instead. Main is merged in as a merge commit rather than a rebase, because 16 of this PR's 25 commits touch the three files that conflicted. This PR keeps its own failure model and uses #791's cause within it:
redacted_failure_detailstores the redacted cause, followed by the correlation ID, for exampleOperationalError in stage12_child_state_create: ... (correlation_id=3f9c...). The cause is shortened, never the ID, to fit the 512-character summary. Typed input and SPM failures, failures a worker already recorded, and cancellations are unchanged.tracked_stage, so a failure names its stage. The coordinator waits on both simulations at once, so it records each one's role while checking it.simulation_invocation_failed, where Record a redacted Stage 12 failure cause instead of only the exception class #791 always usedreport_coordination_failed.format --checkon everysrcdirectory, andgit diff --checkall pass.Rebased onto main after #762, #763 and #795
.github/scripts/stage12-validate-v2-workers.sh, which conflicted with this PR's--cache-manifest-sha256argument. The script now takes the digest as a second required argument and passes it tovalidate_v2_worker_release. The workflow passessteps.stage12_cache.outputs.manifest_digest, the same pattern Move the deploy pipelines' multi-line steps into tested scripts #763 uses to pass step outputs to its other scripts.Build the independent Stage 12 cachestep (stage12-cache-precompute.sh), which runs earlier in the samedeploy_stage12_v2job and writesmanifest_digesttoGITHUB_OUTPUT.RUNNER_TEMPandGITHUB_OUTPUTcome from the runner.MODAL_TOKEN_IDandMODAL_TOKEN_SECRETcome from GitHub Actions secrets, unchanged.test_deploy_workflow_scripts.pychecks that the workflow passes the digest and that the script forwards it. A new test checks that the script fails, without callinguv, when the digest is missing.rules-registry,ci-scripts), pinned Ruff andbash -npass.Rebased onto main after #757 and #787
changelog_entry.yamlkeeps Accept null SPM provenance in Stage 12 aggregate artifacts #787's line and this PR's line.test_coordinator_records_bounded_timeout_without_an_aggregatecombines Accept null SPM provenance in Stage 12 aggregate artifacts #787's valid aggregate stub with this PR'swait_timeout_seconds=0.Stage12ArtifactStore. This PR's four aggregator stubs that must not run now return_aggregate_payload(...), as Accept null SPM provenance in Stage 12 aggregate artifacts #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.rules-registry,ci-scripts) pass.Rebased onto the rules registry (#752)
eef03c3); the only differences are main's changes and the registry entry below.rules-registryguard from Add a rules registry that makes every enforced and unenforced rule visible #752 flaggedtest_stage12_only_deployment_skips_existing_stack_integration_suite, which this PR adds, as a guard test no rule references. It is now one of the nodes ofsim.stage12.deployment-scope. The rule's statement now also says that a Stage 12-only deploy never runs the existing stack's complete integration suite.docs/generated/rules.mdand theAGENTS.mdRules block were re-rendered.python -m scripts.rules guard --base-ref origin/main,scripts/run_quality_guards.pyand the rules tool's own tests pass.tests/test_deployment_assets.py: 113 passed.Validation after rebasing onto #789
uv sync --extra test, plus--lockedto confirm the lockfile is current: PolicyEngine 6.3.4 (policyengine-us 2.2.1, policyengine-uk 2.126.12, policyengine-core 3.33.0).tests/test_stage12_*.py): 198 passed, 1 xfailed.Reconcile segmented Stage 12 execution with current typed provenanceonwards. The four commits before it fail one worker-validation test,test_us_validation_normalizes_the_frontend_reform_interval, exactly as they did before this rebase: main's reform-interval normaliser predates them, and that commit updates the test.format --checkandcheckon the 49 changed Python files: clean. Ruffformat --checkon everyprojects/*/srcandlibs/*/srcdirectory, as CI runs it: clean.git diff --check: clean.Validation of the cancellation and timeout update (before rebasing onto #789)
Full executor suite on Python 3.13 with
uv run --frozen: 809 passed, 23 skipped, 3 deselected. Before that update it was 786 passed.Stage 12 executor tests (
tests/test_stage12_*.py): 181 passed.tests/test_stage12_runtime.pygained 23 tests in that update, covering startup cancellation, cancellation records, Modal fallback, logs, and timing.Regression checks. I reverted each behaviour in turn, and each time the matching new tests failed:
The startup-cancellation, cancellation-log and coordinator-entry tests also failed against the head before that update.
Simulation entry suite: 162 passed. Stage 12 persistence suite: 14 passed. Their cancellation fixtures now use the failed
simulation_cancelledrecord.Scoped Pyright on the coordination, comparison and timeouts modules: 0 errors.
Prior validation before the earlier rebases
projects/policyengine-simulation-executor/tests/test_simulation_output_geographic.py, which this branch does not modify.testingenvironment, including US and UK worker validation and a cache-hit check for the 20-segment, three-year cache.invalid_policy_period, the baseline becameincompletewithcancelled_after_peer_failure(the behaviour at that commit; a cancelled baseline is nowfailedwithsimulation_cancelled), and the report failed with the original validation summary.Earlier testing-environment deployment note
A fresh UK dataset download was blocked because the configured Hugging Face credential could not access the private UK dataset. The testing deployment reused the previously validated UK and coordinator images from the same commit and rebuilt the US image layer with the validated Stage 12 cache.
Earlier current-main reconciliation
The executor keeps main's PolicyEngine 6.3.4 requirements and frozen lockfile; it does not restore older country packages.
Conflict resolution preserves main's output-planning instrumentation and UK metadata validation while retaining concurrent baseline/reform monitoring and segmented US calculation.
Segment merging accepts the current typed
SPMProvenancecontract. Every segment must supply the same complete receipt, including configuration, forecast hash, years and runtime versions; incomplete or inconsistent receipts fail. The merged logical simulation keeps one compact receipt, not a legacyspm_configobject or a growing receipt list. Five regressions cover preservation, missing receipts and mismatched scenario, runtime versions and years.The worker-validation unit test expects the complete reform date interval, matching main's normalizer rather than discarding its end date.
The earlier live results above describe an earlier commit on an older PolicyEngine version, not a fresh 6.3.4 qualification. No deployment has been run on 6.3.4.
🤖 Generated with Claude Code