Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
41 commits
Select commit Hold shift + click to select a range
8cc1e50
Carry canonical SPM choices and receipts through simulation workers
MaxGhenis Sep 9, 2026
7663b0d
Merge remote-tracking branch 'origin/main' into max/spm-simulation-ca…
MaxGhenis Sep 9, 2026
dcfe4fd
Preserve unavailable SPM year errors across worker transport
MaxGhenis Sep 9, 2026
c34f0e4
Track PR677 Fable fixes and verification plan
MaxGhenis Sep 9, 2026
c3b47a4
Add isolated installed-wheel qualification harness for Fable fixes
MaxGhenis Sep 9, 2026
1d6a6ed
test: reproduce SPM legacy routing and partial selection regressions
MaxGhenis Sep 9, 2026
8a7f6e8
Record upstream identity and reproduced Fable regressions
MaxGhenis Sep 9, 2026
f4cc5ea
test: reproduce worker SPM year and scenario error boundaries
MaxGhenis Sep 9, 2026
80c08f7
Document authenticated import order and handoff fingerprints
MaxGhenis Sep 9, 2026
0bf61df
fix: preserve proven historical SPM routes and isolate bundle capabil…
MaxGhenis Sep 9, 2026
38020ce
fix: preserve calculator SPM year and scenario errors in worker
MaxGhenis Sep 9, 2026
2038778
test: reproduce incomplete SPM artifact and precompute key failures
MaxGhenis Sep 9, 2026
56da167
docs: record Fable routing fixes and regression evidence
MaxGhenis Sep 9, 2026
c97d339
Refresh gateway SPM schema and verify entrypoint contract parity
MaxGhenis Sep 9, 2026
9d16eff
test: reject malformed legacy seed and sibling metadata
MaxGhenis Sep 9, 2026
2ee006d
fix: reject incomplete legacy route and sibling metadata
MaxGhenis Sep 9, 2026
35f17d0
docs: record adversarial route provenance qualification
MaxGhenis Sep 9, 2026
728f462
Record passing worker regressions and installed type comparison
MaxGhenis Sep 9, 2026
580673c
Reject temporary-directory import shadowing in qualification
MaxGhenis Sep 9, 2026
c431d13
fix: recompute incomplete SPM artifacts and verify storage keys
MaxGhenis Sep 9, 2026
2384726
Record qualified Fable fixes, source binding and delivery blocker
MaxGhenis Sep 9, 2026
7e88676
Keep review evidence outside the product source
MaxGhenis Sep 9, 2026
b0447ca
Fix isolated service coverage for explicit SPM dates
MaxGhenis Sep 10, 2026
a11c4ae
Add progress tracker for review fixes
MaxGhenis Sep 11, 2026
b074b95
Keep resolved SPM nulls on the wire and legacy bodies unchanged
MaxGhenis Sep 11, 2026
0c3f9c6
Cover segmented national SPM reduce end to end
MaxGhenis Sep 11, 2026
4992a19
Derive legacy route provenance from route shape, not registry generation
MaxGhenis Sep 11, 2026
94e980e
Cover budget-window scheduler typed and redacted child failures
MaxGhenis Sep 11, 2026
bf215fb
Record medium 2-4 and low 1-3 progress
MaxGhenis Sep 11, 2026
bf6764c
Pin the null-preserving serializer at the contract layer
MaxGhenis Sep 11, 2026
638b7c6
Exercise the SPM receipt guard in hermetic CI
MaxGhenis Sep 11, 2026
ae9489e
Hold the storage id against the wrapper that names the file
MaxGhenis Sep 11, 2026
215d6fa
Make an unstated bundle model version mean one thing
MaxGhenis Sep 11, 2026
3b28b9a
Key the SPM artifact cache tests on the storage id
MaxGhenis Sep 11, 2026
2b52202
Show the precompute write path publishing under a shared storage id
MaxGhenis Sep 11, 2026
5809d5b
Format the gateway SPM route tests
MaxGhenis Sep 11, 2026
19e27f8
Resolve an SPM selection once per container, not once per call site
MaxGhenis Sep 11, 2026
3edb78b
Record every finding closed
MaxGhenis Sep 11, 2026
fd869e7
Close the gaps an adversarial audit found in the storage-id and sched…
MaxGhenis Sep 11, 2026
a1999a4
Record the re-audit pass
MaxGhenis Sep 11, 2026
054662a
Drop the review-lane progress tracker from the repository root
MaxGhenis Sep 11, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -254,6 +254,7 @@ def build_batch_status_response(
child_jobs=state.child_jobs,
result=state.result,
error=state.error,
errors=state.errors,
resolved_app_name=state.resolved_app_name,
policyengine_bundle=state.policyengine_bundle,
run_id=state.run_id,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,11 +14,16 @@
model_validator,
)

from policyengine_simulation_contract.spm import (
SPMSelection,
SPMCapability,
SPMComparisonProvenance,
SPMErrorDetail,
)
from policyengine_simulation_contract.json_types import JsonObject
from policyengine_simulation_contract.macro_output import SingleYearMacroOutput
from policyengine_simulation_observability.telemetry import TelemetryEnvelope


# Hard cap on request body size (bytes). SimulationOptions + telemetry + any
# reform/baseline parameter tree should fit comfortably in ~256 KB. A hostile
# client that tries to stream a multi-MB reform dict is rejected with 422
Expand Down Expand Up @@ -95,6 +100,7 @@ class GatewayRequestBase(BaseModel):
"""

country: str
spm: Optional[SPMSelection] = None
version: Optional[str] = None
policyengine_version: Optional[str] = None
telemetry: TelemetryEnvelope | None = None
Expand Down Expand Up @@ -156,6 +162,17 @@ class PolicyEngineBundle(BaseModel):
policyengine_version: Optional[str] = None
data_version: Optional[str] = None
dataset: Optional[str] = None
spm: Optional[SPMCapability] = None


class SimulationErrorResponse(BaseModel):
"""Existing route errors and public typed SPM input failures."""

status: Literal["failed"] | None = None
result: None = None
error: str | None = None
errors: list[SPMErrorDetail] | None = None
detail: str | None = None


class JobSubmitResponse(BaseModel):
Expand All @@ -176,6 +193,7 @@ class JobStatusResponse(BaseModel):

status: Literal["running", "complete", "failed"]
result: Optional[SingleYearMacroOutput] = None
errors: Optional[list[SPMErrorDetail]] = None
error: Optional[str] = None
resolved_app_name: Optional[str] = None
policyengine_bundle: Optional[PolicyEngineBundle] = None
Expand Down Expand Up @@ -223,6 +241,8 @@ def validate_end_year(self) -> "BudgetWindowBatchRequest":
class BudgetWindowAnnualImpact(BaseModel):
"""Annual budget-window impact row."""

spm_config: Optional[SPMSelection] = None
spm_provenance: Optional[SPMComparisonProvenance] = None
year: str
taxRevenueImpact: float
federalTaxRevenueImpact: float
Expand Down Expand Up @@ -265,6 +285,7 @@ class BatchChildJobStatus(BaseModel):
"failed",
"cancelled",
]
errors: Optional[list[SPMErrorDetail]] = None
error: Optional[str] = None


Expand Down Expand Up @@ -292,6 +313,7 @@ class BudgetWindowBatchStatusResponse(BaseModel):
failed_years: list[str] = Field(default_factory=list)
child_jobs: dict[str, BatchChildJobStatus] = Field(default_factory=dict)
result: Optional[BudgetWindowResult] = None
errors: Optional[list[SPMErrorDetail]] = None
error: Optional[str] = None
resolved_app_name: Optional[str] = None
policyengine_bundle: Optional[PolicyEngineBundle] = None
Expand Down Expand Up @@ -323,6 +345,7 @@ class BudgetWindowBatchState(BaseModel):
default_factory=dict
)
result: Optional[BudgetWindowResult] = None
errors: Optional[list[SPMErrorDetail]] = None
error: Optional[str] = None
created_at: str
updated_at: str
Expand All @@ -348,6 +371,15 @@ class VersionMap(RootModel[dict[str, str]]):
class VersionsResponse(BaseModel):
"""All supported simulation routing version maps."""

spm_capabilities: dict[str, SPMCapability] = Field(
default_factory=dict,
description=(
"Canonical SPM capabilities keyed by exact PolicyEngine wrapper version. "
"Resolve a country-model route to its app in the routing maps, then "
"find that app's exact version in the policyengine map. App names, "
"country-model versions and latest aliases are not capability keys."
),
)
policyengine: VersionMap
us: VersionMap
uk: VersionMap
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@

from pydantic import BaseModel, ConfigDict, RootModel

from policyengine_simulation_contract.spm import SPMSelection, SPMComparisonProvenance

T = TypeVar("T")

Expand Down Expand Up @@ -188,6 +189,9 @@ class CongressionalDistrictImpactOutput(MacroOutputModel):
class SingleYearMacroOutput(MacroOutputModel):
"""Completed response returned by a single-year macro simulation."""

spm_config: SPMSelection | None = None
spm_provenance: SPMComparisonProvenance | None = None

model_version: str
data_version: str
budget: BudgetaryImpact
Expand Down
Loading