Repository navigation
Conversation
anth-volk
added this pull request to stack #838
October 19, 2026 21:51
2 tasks done
When the dispatch context's result_delivery is return_to_caller, run_single_simulation reads and writes no Stage 12 row and builds no database store. It checks the policy, calculates the simulation (a segmented US run is never told to stop through the database), stores the input and Parquet artifact as before, and returns the artifact descriptor. A failure raises ReportExecutionError with the same redacted error code and summary a Stage 12 row would record. The default stage12_database delivery runs the same steps as before; the calculation and failure-detail steps move into helpers both modes share. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
When the dispatch context's result_delivery is return_to_caller, the report coordinator writes no Stage 12 rows and builds no database store. It takes no parent record, does not claim the report (the caller deduplicates), plans the output, starts the baseline and reform simulations with the same delivery, waits for both within the shared window, reads and checks their artifacts as the Stage 12 path does, and aggregates them. It writes no aggregate artifact. It returns a ReportExecutionResult whose aggregate is validated as SingleYearMacroOutput and must describe the report. A failure is reported once, recorded as the operation's cause and raised as ReportExecutionError with the redacted detail a Stage 12 row would record; a simulation's own ReportExecutionError takes precedence over its call error. A child that must stop is cancelled through Modal, since no record can tell a segmented child to stop. The Modal coordinate_report function's parent argument becomes optional, and a returned report's coordinator operation carries a result_delivery attribute. The default stage12_database path is unchanged; its planning, child wait and artifact checks move into helpers both modes share. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
_observe_simulations takes the failure and cancellation handlers that the Stage 12 and returned-report paths supply. They were typed Callable[..., Stage12FailureDetail] and Callable[..., None], so a type checker accepted a handler with any arguments, and _cancel_returned_simulations could drop its detail keyword without any check noticing. Two private Protocols now state the keyword arguments each handler receives; pyright reports a handler that does not accept them. _read_simulation_outputs declared its stage_span as StageScope, which requires an attributes argument, but calls it with the stage alone. Its annotation now names the one-argument form it uses. Typing-only change: behavior is unchanged, so no test can fail first. The existing Stage 12 and returned-report tests pass, and pyright reports no errors in the coordination module. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
anth-volk
force-pushed
the
apiv2/1b-report-return-mode
branch
from
October 20, 2026 13:14
b18e832 to
cbb35b1
Compare
2 tasks done
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 #835
Same-Repository Draft PR Check
PolicyEngine/policyengine-sim-api, not a personal fork.Summary
Second of two stacked PRs; it is based on #836, which adds
ReportExecutionResult,ReportExecutionErrorandStage12InvocationContext.result_delivery. This PR adds the return mode to the v2 Modal report coordinator and its simulation workers, for the entrypoint's v2 economy path (a later PR) to call. Withresult_delivery = return_to_caller, nothing reads or writes Stage 12 rows and no database store is built.Coordinator (
stage12_runtime.coordinate_report, Modalcoordinate_report)ValueError) and checks the application, worker version and bundle digest as the Stage 12 path does.stage-12-runs/<environment>/<YYYY>/<MM>/<evaluation_id>, built from the context. A path the caller supplies is replaced, as the Stage 12 path replaces it with one built from the parent row.SingleYearMacroOutput, and returns aReportExecutionResultpayload. It writes no aggregate artifact and does no production comparison.ReportExecutionErrorwith the redacted code and summary a Stage 12 row would record. A worker's ownReportExecutionErrortakes precedence over its call error, as a Stage 12 worker's recorded failure does.Workers (
stage12_runtime.run_single_simulation, Modalrun_single_simulation_us/_uk)ReportExecutionErrorwith the redacted detail, including a segment's failure and typed input errors such asinvalid_policy_period.Stage 12 behavior is unchanged and remains the default. The output planning, child wait, artifact checks and worker calculation move into helpers both modes call. The child wait takes the failure and cancellation handlers as arguments: the Stage 12 path passes its existing record-writing handlers, and the full Stage 12 test suite passes unmodified.
Modal application (
src/modal/v2_app.py)coordinate_report'sparentargument defaults toNone. The Stage 12 entrypoint still passes all three positional arguments.result_delivery=return_to_caller, so telemetry tells it apart from Stage 12 runs. Stage 12 operations keep exactly their current attributes.Known limitations, for the v2 economy path to decide
evaluation_idfor each attempt.SIMULATION_ARTIFACT_BUCKETlater.What a merge deploys
Merging to
mainruns the complete staging and then production deployment. The redeployed v2 Modal application (policyengine-simulation-v2-py<version>) gains the return mode, but nothing calls it yet. The entrypoint sends noresult_delivery, so every Stage 12 report keeps its current behavior. No image, function resource setting, timeout, secret attachment or workflow changes.Environment variables
This PR adds no environment variable, workflow input or secret. Variables the changed runtime code reads:
STAGE12_ARTIFACT_BUCKET(both modes, read byartifact_store()in the coordinator and workers). Provider: the GitHub environment variableSTAGE12_ARTIFACT_BUCKET, present inbetaandprod. Wiring: the deploy workflow passes it in the env of the "Synchronize the separate Stage 12 runtime secret" step.stage12-sync-modal-secrets.shwrites it into the Modal secretstage12-evaluation-runtime, andv2_app.pyattaches that secret to every v2 function (worker_secrets). The variable's value was not inspected.STAGE12_DATABASE_URL(Stage 12 mode only; return mode never reads it). Provider: the Secret Manager secret named by the GitHub environment variableSTAGE12_DATABASE_URL_SECRET_NAME(present inbetaandprod). It reaches Modal through the same sync step and the same Modal secret. Unchanged by this PR; the secret's content was not verified.GOOGLE_APPLICATION_CREDENTIALS_JSON(both modes, read bysetup_gcp_credentialswhenStage12ArtifactStorebuilds its Cloud Storage client, so the return mode needs it for every artifact read and write in the coordinator and workers). Provider: the Secret Manager secret named by the GitHub environment variableSTAGE12_GCP_CREDENTIALS_SECRET_NAME, in the project named bySIMULATION_ENTRYPOINT_GCP_PROJECT_ID(both present inbetaandprod). Wiring: the same "Synchronize the separate Stage 12 runtime secret" step passes both variables tostage12-sync-modal-secrets.sh, which writes the credential into the Modal secretstage12-evaluation-gcp-credentials;v2_app.pyattaches that secret to every v2 function (worker_secrets). Unchanged by this PR; the secret's content was not verified.MODAL_ENVIRONMENT(read by the Modalcoordinate_reportfunction, which this PR changes, only to label its telemetry; it falls back tolocalwhen unset). Unverified: no workflow, script or Modal secret in this repository provides it to the deployed functions, and whether Modal sets it inside containers was not confirmed. Unchanged by this PR.The calculation both modes run is the code the Stage 12 path already runs, using the datasets and cache built into the worker images at deploy time; this PR changes neither.
Coordination with other PRs
coordination.py,simulation.py,failures.pyandv2_app.py, and moves coordination tests into a new test module. A rebase will be needed after whichever merges first.failures.py,test_stage12_runtime.pyandtest_stage12_modal_app.py.src/modal/v2_app.py. A conflict in that file is likely but small: this PR changes only the coordinator's signature, docstring and operation attributes, and one import.Testing
All new tests are in the executor project.
test_stage12_runtime.py, returned simulations (6 tests): artifact and descriptor without any database access, a given store left unused, the redacted typed failure, a typed input failure, a segmented run never told to stop, and a segment's failure kept.test_stage12_runtime.py, returned reports (14 tests):SingleYearMacroOutput, of one for another report, and of artifacts that do not follow the plan.test_stage12_modal_app.py(2 tests): the Modal coordinator runs a returned report without a parent and labels its operation, and Stage 12 operation attributes are unchanged.ruff check .andruff format --check projects/*/src libs/*/srcwith the pinned ruff 0.15.22 pass.scripts/run_quality_guards.pypasses. pyright 1.1.401 reports no errors instage12_runtime/coordination.py.🤖 Generated with Claude Code