Minimal test-user workbench for integrated energy-development scenario runs.
Start with the two primary documents:
Supporting technical documentation:
- Documentation index
- System documentation
- Modeling methodology technical reference
- Backend handoff
- Frontend handoff and deferred backend work
- Model I/O catalog
The repository now ships with seeded placeholder expert datasets so the full workflow can run end-to-end without empty tables. These seeded values are internally coherent and materially better than the original 4-row samples, but they are still placeholders. They should not be treated as project-calibrated evidence.
The local UI prints validation and placeholder diagnostics in the Environment setup panel. analysis and full
profiles use strict validation automatically; the local reference implementation allows seeded placeholder data so the
full workflow can still be tested end-to-end.
-
inputs/mario_inputs/employment_intensity.csv- Purpose: direct and total jobs intensities used by the MARIO development runtime.
- Current status: now populated with seeded placeholder rows covering 5 MARIO regions and 10 energy-relevant sectors.
- Required action: replace every placeholder row with calibrated
jobs_per_musd_directandjobs_per_musd_totalvalues for each(mario_region, mario_sector)combination that can appear in exchange shocks. - Completion rule: no placeholder rows remain;
sourcecites the real study/database;reference_yearmatches the monetary basis of the MARIO table.
-
inputs/mario_inputs/value_added_intensity.csv- Purpose: GVA and household-income multipliers used by the MARIO development runtime.
- Current status: now populated with seeded placeholder rows covering 5 MARIO regions and 10 energy-relevant sectors.
- Required action: replace every placeholder row with calibrated
gva_per_musd_outputandhousehold_income_per_musd_outputvalues for each(mario_region, mario_sector)used by the model. - Completion rule: no placeholder rows remain;
sourcecites the real evidence base; units are consistent with the MARIO monetary year.
-
inputs/mario_inputs/scenario_assumptions.csv- Purpose: exogenous scenario assumptions used by integrated indicator reporting.
- Current status: now populated with seeded placeholder rows for the active EDIM scenario keys plus
baseline. - Required action: replace placeholder rows with scenario-specific or
baselineassumptions. The runtime currently consumes matched assumptions for indicator reporting, especiallycarbon_price; unmatched rows are preserved as metadata. - Completion rule: no placeholder rows remain in the matched scenario/baseline rows;
scenario_keyvalues are real scenario identifiers orbaseline; units are explicit.
-
inputs/generated/africa_national_mrio_placeholder_scenarios.json- Purpose: national target-pathway records used when the integrated scenario setup chooses
S1orS2; the MRIO shock-mapping selector only controls how those targets become A/Z, E, and Y shock rows. - Current status: generated from structured inputs in
inputs/generated/scenario_report_scenarios.json,inputs/mario_inputs/scenario_report_scenarios.csv, and the African country seed list. South Africa uses the dedicatedZA-S1/ZA-S2records; every other African country usesWF-S1/WF-S2Rest-of-Africa assumptions as a national placeholder. - Required action: replace placeholder country records with expert national MRIO scenario assumptions when available,
preserving the
S1full-decarbonization andS2national-policy-target archetype structure. - Completion rule: each national record has country-specific provenance, no non-South-Africa record depends on
WF-S1/WF-S2, and generated diagnostics report zero placeholder national MRIO records.
- Purpose: national target-pathway records used when the integrated scenario setup chooses
inputs/mario_inputs/development_indicator_mapping.csv- Purpose: maps modeled metrics to reported development indicators.
- Current status: seeded with supported driver mappings and fully usable for placeholder runs.
- The runtime currently computes all seeded rows directly from existing model outputs.
frontend/geo/edim_locations_placeholder.geojsonis still a placeholder model-location geometry asset.frontend/geo/countries.geojsonis the consolidated country-boundary file used for country/subregion rendering.- When explicit subregion polygons are missing, the frontend synthesizes country subregions from centroid points and
Voronoi partitioning inside parent-country boundaries from
countries.geojson. - This is acceptable for exploration, not for final cartography. Replacing these shapes is a GIS task, not an energy calibration task.
-
Start from the active tech-sector mapping.
- Review
inputs/mario_inputs/calliope_tech_to_mario_sector.csv,inputs/mario_inputs/capex_sector_split.csv, andinputs/mario_inputs/opex_sector_split.csv. - Enumerate the
(mario_region, mario_sector)pairs that can actually appear in the exchange shocks.
- Review
-
Fill intensity tables at that exact resolution.
employment_intensity.csv: one row per(mario_region, mario_sector).value_added_intensity.csv: one row per(mario_region, mario_sector).- Avoid region averages unless no sector-specific evidence exists; if averaging is unavoidable, document it in
notes.
-
Use consistent monetary conventions.
- Intensities are interpreted per
1 MUSDof modeled output/shock. reference_yearshould match the IO table year or the deflated target year used to build the table.- If source data are in local currency, convert them before entry and document the FX/deflator basis in
notes.
- Intensities are interpreted per
-
Replace placeholder provenance with real provenance.
- Do not leave
source=placeholder. - Put the actual data source or study name in
source. - Use
notesfor caveats, imputation rules, and any sector aggregation.
- Do not leave
-
Populate scenario assumptions against real scenario keys.
- Use
scenario_key=baselinefor shared defaults. - Use an exact EDIM scenario key when an assumption is scenario-specific.
- Keep
unitexplicit, for exampleusd_per_tco2,multiplier,index.
- Use
-
Validate before treating results as final.
- In the UI, select
analysisorfullprofile to run strict validation automatically. - The run should pass environment setup without placeholder expert datasets, incomplete MARIO mappings, or invalid CAPEX/OPEX share groups.
- The resulting run-level diagnostics should show
Placeholder rows: 0.
- In the UI, select
Use Python 3.11.
python3.11 -m venv backend/.venv
source backend/.venv/bin/activate
pip3 install -U pip
pip3 install -r backend/requirements.txt
pip3 install -r backend/requirements-dev.txt
pip3 install --no-build-isolation -e ./model_runtimecd frontend
npm install
npm run build
cd ..energy-modelingThe runner starts FastAPI with the same project-owned, black-box model handoff path used for backend deployment. It
tries the requested port first (8000 by default), then automatically picks the next available port if that port is
already in use. It also opens the UI automatically in the default browser when the app is ready.
If the user-local launcher has not been installed, run the repo-local launcher instead:
scripts/energy-modelingFor debugging, the underlying Python entry point remains available:
backend/.venv/bin/python scripts/run_local.py --no-openThe app opens automatically. If needed, open:
http://127.0.0.1:8000/ui/
If the runner selected another port, use the URL printed in the terminal.
- Select or create a project from the dashboard header.
- Select scenario, target pathway, target year, run profile, and levers.
- Confirm Environment setup is ready.
- Click Queue run.
- Monitor status in the project run tabs and the environment/operations panel.
The canonical UI flow is project-owned: the frontend creates a draft run under
/api/projects/{project_id}/runs, submits that draft, then polls the resulting
execution_id.
After a run succeeds, the same dashboard supports:
- Results mode for the selected run.
- Compare mode across completed runs in the active project.
- Project report generation, including Markdown and structured source-data JSON.
- Single-run and project export bundle downloads.
- Input dataset upload/download plus version activation/deletion.
Project records, runs, reports, exports, and dataset overrides are linked to
the active user. The seeded admin test user can see all user-owned projects;
normal test users see only their own records.
Run artifacts are written to:
outputs/runs/<run_id>/
Project reports and export bundles are written to:
outputs/platform/reports/outputs/platform/exports/
Each generated report has:
<report_id>.md<report_id>.source.json
The source JSON uses schema edim_project_report_source_v1 and is built from
project metadata, selected project runs, run summary artifacts, and export
records. It is deliberately basic for now so future report renderers can consume
the same backend source-data contract.
Dataset uploads are written as user-owned immutable versions under:
outputs/dataset_uploads/users/<user_id>/<dataset_id>/
Main run outputs include:
inputs/request_bundle.jsoninputs/scenario_package.jsonartifacts/final/results.csvartifacts/final/summary.jsonartifacts/final/development_impacts.jsonartifacts/final/integrated_results.jsonexports/report.mdexports/exchange_bundle.zip
All UI downloads should go through artifact ids or project/report/export descriptors returned by the API. Do not build new frontend code that infers filesystem paths.
Project report and export records expose storage_ref objects with
provider/object-key metadata. Local development resolves those references to
outputs/platform/...; cloud storage should replace them with Blob/container
keys without changing frontend download URLs.
The handoff structure is intentionally simple. Run cd frontend && npm run build to validate and create the compact static bundle in frontend/dist/ for deployment:
- Frontend shell: renders the basic landing page, projects, the graph-centered model workspace, run controls, result panels, compare mode, reports, exports, and dataset versions.
- Backend API/orchestration: owns auth context, project/run/report/export records, dataset metadata, artifact access, run queueing, and progress/status.
- Black-box model runtime: consumes one run bundle, emits progress events, writes declared artifacts, and returns a final summary.
Backend/cloud developers should replace infrastructure providers, not model or route logic:
- Auth provider: replace
get_current_user_context. - Platform repository: replace
PlatformRepository(the local reference implementation is SQLite-backed). - Dataset repository: replace
DatasetRepository. - Artifact storage: replace
ArtifactStorageService. - Runtime event store: replace
EventStore. - Queue/worker: replace local
JobManager/LocalExecutionQueuewith a durable queue and worker usingexecution_queue_message.
Local development now enqueues the same execution_queue_message payload that
cloud workers should consume. The payload is persisted in the project run record
as execution_queue_message and embedded in each run bundle as queue_message.
Each run record also stores execution_attempts using execution_attempt,
including worker id, heartbeat, cancellation, and terminal attempt status.
Frontend/platform developers should keep using the API client boundary in
frontend/app.jsx rather than hard-coding URLs inside components.
The dashboard header includes a runtime target switch for backend testing:
Local: calls the same origin that served the app, normallyhttp://127.0.0.1:8000.Backend: calls the hosted backend URL configured by the frontend runtime environment.
Set the backend target with EDIM_BACKEND_API_BASE before starting or building
the frontend. The local runner and frontend build script also read this key from
repo-root .env if it is not exported in the shell:
EDIM_BACKEND_API_BASE=https://your-hosted-backend.example.org python3 scripts/run_local.py --port 8000
cd frontend
EDIM_BACKEND_API_BASE=https://your-hosted-backend.example.org npm run buildSwitching runtime targets clears the loaded workspace state and reloads session,
projects, datasets, runtime catalogs, and scenario catalogs from the selected API.
If EDIM_BACKEND_API_BASE is not set, the Backend side of the switch is disabled.
This variable is a public API URL only; never put secrets in frontend runtime config.
On switch, the frontend first probes GET /api/system/manifest and displays
Contract ok, Contract warning, or Contract error in the header. Backend
mode is not used if the manifest is unreachable, has the wrong schema, or reports
failed diagnostics.
Run the handoff smoke test against the same subprocess runtime contract used in deployment:
source backend/.venv/bin/activate
python3 scripts/run_local.py --port 8000
python backend/tools/backend_handoff_smoke.py --base-url http://127.0.0.1:8000 --timeout-seconds 900The smoke test validates session/user context, the machine-readable system
manifest, project creation, dataset catalog, runtime catalog, environment setup,
draft run creation, run submission, status polling, runtime events, artifact
downloads, report generation, run export, and project export.
By default it uses the lightweight energy-only architecture with the
transmission-only new_links scenario and dev time slice. To run the full
bridge/MRIO integration smoke, add --model-architecture-id energy-development.
It still runs the real packaged model, so the timeout needs to allow several
minutes for local Calliope solves.
The local run package remains:
outputs/runs/<run_id>/
Primary declared artifacts remain:
summary_jsonintegrated_results_jsondevelopment_impacts_jsonresults_csvreport_markdownexchange_bundle_zip
These are resolved through:
GET /api/runs/{run_id}/artifacts/{artifact_id}
Do not depend on physical file paths from frontend or cloud code.
The codebase is now split so TVA can treat the model runtime as a black box more easily:
backend/api_service/main.py- Thin FastAPI composition root and route surface.
backend/api_service/services/- Backend-facing application services for dataset catalogs and run artifact resolution.
backend/api_service/runtime/- Backend execution contracts, queues, event parsing, and run stores.
model_runtime/edim_model/contracts.py- Shared artifact registry, run package layout, retention policy loader, and runtime event helpers used by both the backend adapter and the executable model package. This keeps artifact behavior in one place without coupling the model runtime back to the FastAPI service.
backend/api_service/adapters/- Execution adapters.
SubprocessModelRuntimeis the black-box hosting path.
- Execution adapters.
model_runtime/edim_model/- Executable model package. It exposes
runandpreflightcommands throughpython -m edim_model.cli. - The current real runtime imports packaged model core from
model_runtime/edim_model/core, not backend API modules. architecture_catalog.jsonis the model-owned architecture graph/result surface catalog served throughGET /api/model-runtimes.- Model-specific layers are registered under
model_runtime/edim_model/modules/:calliopeowns the executable energy layer,osemosysdeclares the planned but disabled OSeMOSYS boundary, andmrioowns the development-impact layer. - Scenario selectors are module-owned. Each model module contributes
scenario_channelssuch asscenario.energy_scenario_key,scenario.target_scenario_id, orscenario.mrio_shock_mapping_id;/api/scenariosaggregates those channels for the frontend. Future modules should add their own channels instead of extending a global "energy scenario versus MRIO scenario" switch.
- Executable model package. It exposes
model_runtime/model_modules/- Bundled model source/data assets by engine. The current Calliope-Africa model is under
model_runtime/model_modules/calliope/Calliope-Africa-main/; future large model assets should be added as sibling engine folders instead of repository-root folders.
- Bundled model source/data assets by engine. The current Calliope-Africa model is under
frontend/dist/- Generated static frontend deployment bundle.
model_runtime/edim_model/architecture_catalog.json- Canonical model-owned architecture catalog used by both
GET /api/model-runtimesand the frontend static build.
- Canonical model-owned architecture catalog used by both
frontend/app.jsx- Single-file dashboard shell containing the UI, API client, workspace artifact helpers, dataset controls, and result artifact components. The app intentionally stays consolidated for handoff simplicity while keeping backend calls behind the in-file API client boundary.
The platform API is project-owned and run-centric. The frontend should create
drafts through POST /api/projects/{project_id}/runs, submit with
POST /api/projects/{project_id}/runs/{run_id}/submit, poll
the compact GET /api/executions/{execution_id}/status, and download declared outputs through
GET /api/runs/{run_id}/artifacts/{artifact_id}. The public run-output contract is
artifact_catalog; the backend no longer infers model output paths. Run
outputs and artifact downloads are authorized through the run record owner/admin
policy before files are resolved. The local platform API now uses a replaceable
test-user context, links projects/datasets/runs/reports/exports to an owning
user, rejects unknown test-user headers, and includes an admin test account that
can see all user-owned projects.
The backend now prepares a manifest-driven run bundle and launches the selected model runtime through an executable adapter.
- Execution identity:
execution_ididentifies the queue/worker attempt.run_idis a 32-character hex id allocated at submission and is the stable artifact namespace for results, comparison, exports, and reports.
- Model manifest:
model_runtime/edim_model/model_manifest.json- Declares model id/version, entrypoint, supported schemas, required inputs, declared outputs, stages, and resource expectations.
- Dataset manifest:
model_runtime/edim_model/dataset_manifest.json- Declares model-owned input datasets, paths, required status, scope, and upload policy.
- Run bundle:
outputs/runs/<run_id>/inputs/request_bundle.json- Immutable model request containing the backend-normalized user configuration, model manifest snapshot, dataset manifest snapshot, artifact policy, runtime settings, and scenario package content where available.
- Runtime events:
outputs/runs/<run_id>/logs/runtime_events.jsonl- JSONL event stream with
runtime_event_v1objects for progress, warnings, errors, and final result emission. Default runtime mode is configured ininputs/runtime_config.jsonunder:
- JSONL event stream with
{
"model_runtime": {
"mode": "subprocess",
"artifact_handoff_mode": "shared_filesystem",
"dataset_staging_mode": "copy_to_run",
"manifest_path": "./model_runtime/edim_model/model_manifest.json",
"dataset_manifest_path": "./model_runtime/edim_model/dataset_manifest.json"
}
}artifact_handoff_mode is part of the backend system manifest:
shared_filesystem: local default, where runtime artifacts stay underoutputs/runs/<run_id>.worker_staged_upload: recommended Azure target, where the worker uploads declared artifacts through the injected artifact storage provider before terminal status.runtime_direct_upload: reserved for future runtimes that publish directly to object storage.
Completed runs include artifact_publication diagnostics in summary.json so deployment teams can confirm how artifacts were handed from the model runtime to the API/download layer.
dataset_staging_mode controls how input datasets are handed to the runtime:
copy_to_run: local default, where inputs are copied intoinputs/datasets/<dataset_id>/in the run package before execution.reference: development-only mode where the run bundle references resolved active input paths.object_reference: cloud-provider mode for durable object-storage references.
Every run bundle includes dataset_manifest.dataset_staging.schema_version = dataset_staging_v1 plus per-dataset staging status, storage references, file hashes, and sizes where available.
For cloud deployment, the backend should keep the same interface and replace only the adapter implementation:
- Local development:
SubprocessModelRuntime - Container worker: future
ContainerModelRuntime - Azure Batch / Kubernetes / queue worker: future
RemoteJobModelRuntime
The configured local platform store is SQLite (storage.platform_store_backend = sqlite in inputs/runtime_config.json). It stores project/run/report/export metadata transactionally under outputs/platform/platform.sqlite3, keeps large artifacts on disk, and imports existing JSON indexes when the SQLite database is first created. There is no active JSON repository path; hosted deployments should replace PlatformRepository with a managed database implementation rather than adding another local persistence mode.
Backend provider injection is explicit through create_app(settings=..., platform_repository=..., artifact_storage=..., dataset_repository=..., event_store=..., job_manager=...). The local defaults are filesystem plus SQLite metadata; hosted deployments should inject cloud database, Blob/object-storage, runtime event, and durable queue providers at that composition root.
Input dataset uploads are stored as user-owned versioned overrides instead of overwriting repository files. Uploads are written under outputs/dataset_uploads/users/<user_id>/<dataset_id>/, with active versions recorded in that user folder. Dataset APIs are intentionally user-scoped, not project-scoped. The run bundle receives a staged snapshot of the selected user’s active datasets through dataset_manifest, so one user’s uploaded inputs do not silently affect another user’s run. Project exports include uploaded dataset files referenced by exported run snapshots under datasets/users/<user_id>/..., making exported workspaces reproducible even when user overrides are outside the run directory. The upload API validates file type, size, parseability, and CSV headers before activating a version. Versions can be listed, reactivated, filtered in the dataset catalog, and deleted through the API.
The route layer uses DatasetRepository for catalog, upload, version, active-pointer, download, and runtime dataset staging behavior. Azure can replace this provider without changing the model runtime contract.
The local reference implementation exposes platform endpoints for TVA/backend integration:
GET /api/sessionGET /api/system/manifestGET /api/projectsPOST /api/projectsGET /api/projects/{project_id}PATCH /api/projects/{project_id}DELETE /api/projects/{project_id}GET /api/projects/{project_id}/runsPOST /api/projects/{project_id}/runsGET /api/projects/{project_id}/runs/{run_id}GET /api/projects/{project_id}/runs/{run_id}/diagnosticsPATCH /api/projects/{project_id}/runs/{run_id}POST /api/projects/{project_id}/runs/{run_id}/submitPOST /api/projects/{project_id}/runs/{run_id}/duplicateDELETE /api/projects/{project_id}/runs/{run_id}GET /api/runs/{run_id}/logsPOST /api/runs/{run_id}/exportGET /api/projects/{project_id}/reportsPOST /api/projects/{project_id}/reportsGET /api/projects/{project_id}/exportsPOST /api/projects/{project_id}/exportsGET /api/scenariosGET /api/input-datasets?layer=<layer>&input_property=<text>&role=<text>GET /api/model-runtimesPOST /api/projects/{project_id}/runs/validateGET /api/input-datasets/{dataset_id}/versionsPOST /api/input-datasets/{dataset_id}/versions/{version_id}/activateDELETE /api/input-datasets/{dataset_id}/versions/{version_id}
The frontend uses the project-owned run flow: create/find a project, create a draft run under that project, submit that
run, and poll by execution_id.
Authentication is still a local test shim, not production auth. The frontend sends X-EDIM-User-Id for one of the seeded test users from GET /api/session; unknown test-user IDs are rejected rather than mapped to an account. Production should replace only this session/dependency layer with authenticated user context while preserving the same owner-user fields, run-artifact authorization, and admin visibility behavior.
The frontend API client exposes a small auth-provider seam through window.EDIM_API_CLIENT.setAuthProvider(...). The default provider writes the local test-user header, but a hosted shell can replace it with a provider that returns bearer-token or managed-session headers without changing dashboard components.
Each run now uses a stable package layout under outputs/runs/<run_id>/:
inputs/- Request bundle, model manifest snapshot, dataset manifest snapshot, artifact policy, scenario package, and staged scenario-side manifests.
work/- Temporary runtime-only files that do not need to be exposed.
artifacts/- Declared intermediate and final artifacts.
logs/- Runtime JSONL events and model logs such as MARIO execution logging.
exports/- Durable export bundles and generated reports.
inputs/runtime_config.json- The
artifacts.manifestsection is now the control surface for retention and exposure policy.
- The
- Each artifact declares:
pathproducer_stagekindretain_on_successretain_on_failureembed_in_summaryembed_in_final_resultsinclude_in_project_bundleexpose_downloadrequired_for_report- optional
drop_after_consumed_by
The runtime registry uses that manifest to decide where files are written and which artifacts are exposed back through the run API.
- Run
devwith strict validation on to catch configuration/data issues cheaply. - Once strict
devpasses, runanalysisorfull. - Review the run-level diagnostics in the UI before using the outputs externally.
The workbench now exposes a synthesized model-quality layer so users do not have to infer trustworthiness from raw warnings alone.
-
Model quality- Combines placeholder usage, mapping coverage, warning count, CO2 method consistency, and pool energy-balance residuals into a score and status.
- Status values:
production_readyanalyst_reviewexploratory_only
-
Metric resolution- Shows the model-native resolution of each major output and what the filtered UI can safely display.
- This is the main guardrail against country-level interpretation of region-only development outputs.
-
System structure- Reports renewable / zero-carbon / fossil generation shares and generation by reporting group.
-
Emissions and energy balance- Physical emissions now prefer direct
cost[costs=co2]accounting when available. - The backend also computes pool-level balance residuals so generation, trade, demand, and unmet demand can be checked for consistency.
- Physical emissions now prefer direct
When reviewing a run, treat the following as blocking for decision-grade use:
Model quality = exploratory_onlyPlaceholder rows > 0- Large pool balance residuals or CO2 method gaps
The frontend is now organized as an architecture-driven dashboard rather than a long scrolling report:
- Model architecture catalog:
GET /api/model-runtimes -> architecture_catalogdefines selectable architecture graphs. - Setup canvas: the selected architecture supplies the visible boxes, arrows, dataset inputs, result tabs, and output artifacts.
- Results canvas:
energy-developmentshowsOverview,Energy system,Development, andMethod;energy-onlyhides MRIO/development tabs and artifacts.
The design intent is to make the model architecture itself the primary UI. Adding a future architecture should mostly
mean adding a new runtime-owned catalog entry plus backend/runtime support for the same model_architecture_id.
EDIM now uses one integrated scenario package per run. Users configure:
model_architecture_id: the selected model graph/result surface, currentlyenergy-developmentorenergy-only.scenario.energy_scenario_key: the Calliope energy pathway.scenario.target_scenario_id: the integrated target pathway id, currentlyS1for full decarbonization orS2for national policy target.scenario.target_year: the year used for structured MRIO assumptions.run_profileand levers.
The frontend sends only the compact run configuration. The backend derives project_id, strict-validation behavior,
placeholder-data policy, dataset snapshots, runtime settings, model manifests, artifact policy, queue metadata, and
execution attempts.
The backend routes that package through architecture-specific channels:
- Energy channel:
IntegratedScenarioPackage -> Calliope adapter -> Calliope solve -> bridge exchange CSVs. - MRIO-direct channel:
IntegratedScenarioPackage target pathway -> MRIO shock mapping adapter -> heuristic A/Z, E, Y inputs. - Energy-only architecture: energy solve and integrated results assembly run; bridge, MRIO-direct, and development runtime stages are skipped and no MRIO/development artifacts are exposed.
Each submitted run bundle and final integrated results payload includes run_provenance, with hashes for the normalized
request, runtime manifest, runtime config, dataset snapshot, and artifact policy. This is the audit handle backend teams
should preserve when moving execution to queue workers or containers.
For now, the system keeps bridge-derived and MRIO-direct outputs side by side. If both channels overlap, headline development totals default to the Calliope bridge-derived values. The structured MRIO-direct effects are retained as diagnostic/secondary outputs under the MRIO-direct heuristic method.
Run artifacts include:
scenario_package.jsonscenario/energy_input_manifest.jsonscenario/report_scenario_reference.jsonscenario/geography_alignment.jsonscenario/mrio_direct_inputs.jsonscenario/mrio_direct_shocks.csv
Structured MRIO scenario targets live in inputs/generated/scenario_report_scenarios.json, with the analyst-readable
CSV extraction at inputs/mario_inputs/scenario_report_scenarios.csv. The backend also generates
inputs/generated/africa_national_mrio_placeholder_scenarios.json, which expands the UI-level S1/S2 selection to
one national MRIO record per African country. South Africa uses the dedicated structured ZA records; other African
countries use Rest-of-Africa assumptions until expert national records are supplied. Caches are keyed by structured input
SHA/provenance and are rebuilt automatically when those structured inputs change.
Geography alignment is controlled by inputs/scenario_geography_mapping.csv. National target scenarios fan out to mapped
Calliope subnational locations for the same parent country. Regional MRIO scenarios fan out to mapped country/location
rows. Mismatches only block when both sides expose incompatible subnational groupings.
PYTHONPATH=backend:model_runtime backend/.venv/bin/python -m pytest backend/tests/test_mvp.py -qsource backend/.venv/bin/activate
python3 backend/tools/smoke_check.py
python3 backend/tools/smoke_check.py --run-model
python3 backend/tools/model_readiness_audit.py --scenario new_links
python3 backend/tools/model_readiness_audit.py --scenario new_links --run-id <run_id>Backend handoff smoke test against an already-running backend:
source backend/.venv/bin/activate
python3 scripts/run_local.py --port 8000
python backend/tools/backend_handoff_smoke.py --base-url http://127.0.0.1:8000 --timeout-seconds 900This validates user/session context, /api/system/manifest, project-owned run
submission, runtime events, artifact-id downloads, report generation, and export
bundle downloads.
docker compose up --build