Halifax reconstruction, time-margin metric, and the operator console - #47
Open
legend5teve wants to merge 45 commits into
Open
Halifax reconstruction, time-margin metric, and the operator console#47legend5teve wants to merge 45 commits into
legend5teve wants to merge 45 commits into
Conversation
Changes to be committed: modified: agentevac/simulation/main.py modified: agentevac/simulation/spawn_events.py modified: agentevac/utils/replay.py modified: sumo/Repaired.netecfg modified: sumo/Repaired.sumocfg
Module updated: agentevac/utils/replay.py
- Fixed RouteReplay._load_schedule(...) so it only reads step and veh_id for replayable events:
- route_change
- departure_release
- Non-replayable events like agent_cognition and metrics_snapshot are now ignored without touching veh_id.
Cause
- The loader was accessing rec["veh_id"] before checking the event type.
- metrics_snapshot records do not have veh_id, so replay loading crashed with KeyError.
Verification
1. python3 -m py_compile agentevac/utils/replay.py passed.
2. Reproduced the failing case with a small local script:
- one route_change
- one agent_cognition
- one metrics_snapshot
- replay load now succeeds and only indexes the route-change step.
…s and agent communication
…t_round_timeline.py
…gs for documentation
…g, and per-agent heterogeneity - Add compute_signal_conflict() using Jensen-Shannon divergence in belief_model.py - Restructure all three LLM prompts (pre-departure, destination, route) to expose raw env vs. social disagreement via your_observation/neighbor_assessment/ information_conflict/combined_belief fields - Add conflict_assessment field to all Pydantic response models - Add conflict recording to metrics (record_conflict_sample, compute_average_signal_conflict) - Implement distance-based noise scaling (proposal Eq. 1): effective sigma scales with fire margin / reference distance via DIST_REF_M config - Add per-agent parameter heterogeneity via sample_profile_params() with truncated normal distributions; configurable via *_SPREAD env vars (default 0 = legacy) - Fix stale subjective_information reference in scenarios.py - Add experiment stage scripts (stages 0-5) for RQ1/RQ2/RQ3 sweeps - Add comprehensive tests for all new features (291 tests passing) Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
… recording - Add observation-based exposure function for no_notice scenario that uses agent belief state and route length instead of route-specific fire data - Enable expected_utility in all three scenarios (no_notice, alert_guided, advice_guided) with scenario-aware LLM policy text - Update menu filtering to retain travel time and utility for no_notice agents - Fix NET_FILE default from .rou.xml (route file) to .net.xml (network file), which caused EDGE_SHAPE to be empty and all exposure scores to be zero - Fix exposure recording to fire only on decision rounds instead of every simulation step, preventing dilution of the exposure average - Add Repaired.net.xml to repo; update SUMO configs to use local net file Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…e parameters Use SIM_END_TIME_S (default 1200s) to control simulation duration instead of relying on getMinExpectedNumber(), which terminated early when no agents had departed yet. Remove dummy t_0 vehicle from route file. Add --sim-end-time CLI flag and SIM_END_TIME_S env var. Update fire source growth rates and timing for more aggressive spread scenarios. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Add input-hash caching (Plan C) across all 3 LLM call sites to skip redundant API calls when agent inputs haven't changed between rounds - Add parallel LLM dispatch (Plan A) for process_pending_departures using ThreadPoolExecutor — two-phase collect-then-process pattern fires all non-cached predeparture LLM calls concurrently (up to MAX_CONCURRENT_LLM) - Add 4 new fields to AgentRuntimeState for cache state tracking - Add RQ1–RQ4 experiment runner scripts for automated parameter sweeps Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Stop the simulation loop as soon as every spawned vehicle has departed and arrived at its destination, instead of running until SIM_END_TIME_S. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Restructure LLM decision prompts with explicit priority levels (safety > official guidance > risk assessment), add EOC guidance_source to operator briefings, and fix early termination to check actual arrivals via metrics.arrived_count() instead of active vehicle count. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…dule-plots # Conflicts: # agentevac/agents/agent_state.py # agentevac/analysis/metrics.py # agentevac/simulation/main.py # sumo/Repaired.netecfg # sumo/Repaired.sumocfg
…etwork updates - Record per-step edge traces via getRoadID() for faithful replay of actual routes taken (not just planned routes) - Add departure destination choice: agents pick a destination via LLM before spawning, so vehicles head the right direction from step zero (parallel LLM dispatch via ThreadPoolExecutor) - Fix early termination to check arrived_count instead of empty vehicle list (prevents premature exit when SUMO defers vehicle insertion) - Replay mode reads to_edge from departure records for correct initial routing - Update SUMO network with new shelter edges (E#S0, E#S1, E#S2) and refreshed spawn_events - Refine scenario prompt suffixes and DecisionModel schema (situation_summary field, expanded reason descriptions) - Update forecast_layer and corresponding tests Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…dule-plots # Conflicts: # agentevac/simulation/main.py # sumo/Repaired.net.xml # sumo/Repaired.netecfg # sumo/Repaired.sumocfg
…selection - Record departure destination choice in metrics via record_decision_snapshot so destination_choice_share counts all agents (not just those processed by process_vehicles) - Replace fixed-offset vehicle selection with round-robin so all agents get mid-route LLM re-evaluation over successive decision ticks Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The experiment runner lacked a --sumo-seed argument, so RQ scripts passed the seed via env var prefix which broke under dash (/bin/sh). Add --sumo-seed to experiments.py and rewrite all four RQ scripts to use POSIX-compatible for-loops with the new flag. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Record each agent's sampled psychological parameters (theta_trust, theta_r, theta_u, gamma, lambda_e, lambda_t) and write them to an agent_profiles JSON file alongside the metrics file. Enables post-hoc verification of population heterogeneity distributions in RQ4 runs. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…stances The old thresholds (danger ≤100m, risky ≤300m, buffered ≤700m) were calibrated for a city-block mental model. In the actual simulation, the minimum observed margin is 619m, so every agent always classified the fire as "safe" and never perceived risk. Scale thresholds to danger ≤1200m, risky ≤2500m, buffered ≤5000m so agents meaningfully perceive fire hazard. Also scale RISK_DECAY_M from 80 to 960 to keep the exponential risk curve proportional. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
En-route agents in no_notice mode can now see fire on the first few edges ahead of their current position (VISUAL_LOOKAHEAD_EDGES, default 3). This adds a penalty to the current destination's exposure score, making agents more likely to switch shelters when fire blocks their route. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…ling _observation_based_exposure() now prefers travel_time_s_fastest_path (minutes * 0.3) over len_edges (count * 0.15) to better reflect actual exposure duration. Falls back to edge count when travel time is unavailable. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…y prompts Adds an explicit instruction to all three LLM policy locations (pre-departure, en-route destination, en-route route) requiring agents to only reference information explicitly present in the prompt data. Prevents GPT-4o-mini from fabricating neighbor behaviors, evacuation patterns, or shelter choices that cascade through the messaging system. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Agents in no_notice mode now only perceive fires within FIRE_PERCEPTION_RANGE_M (default 1200m) of their position: - Perception horizon: if no fire is in range, env_signal margins are None → observed_state="unknown" (genuine uncertainty instead of false "safe"). When fire is in range, margins are computed from visible fires only. - Route-level fire data: all reachable menu items gain proximity_blocked_edges and proximity_min_margin_m from visible fires, enabling the utility function to differentiate destinations by hazard. - Exposure scoring: _observation_based_exposure() adds a proximity penalty (blocked * 8.0 + margin_penalty) matching _expected_exposure weights, so routes through visible fire are strongly deprioritised. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…nd compact JSON encoder Functional updates: - Extract AgentMessagingBus and OutboxMessage from main.py into agentevac/agents/messaging.py with spatial filtering support (comm_radius_m parameter for distance-based broadcast delivery) - Add filter_history_for_scenario() in scenarios.py to sanitize agent self-history records before embedding in LLM prompts (strips forecast, advisory, fire metrics per information regime) - Add _CompactLeafEncoder in run_parameters.py for readable parameter log output (leaf dicts rendered on single lines) - Add agentevac/analysis/analyze_run.py run analysis utility - Add tests for messaging spatial filtering (test_messaging.py) and history filtering (test_scenarios.py) - Add Research_Proposal_0317.pptx to .gitignore Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…rust enforcement, and spatial messaging Functional updates in agentevac/simulation/main.py: DEPARTURE PROMPT: - Replace BINDING CONSTRAINT with DECISION RULE prompt — 4 ordered rules (p_danger > theta_r, heuristic_departure_signal, official order, else wait) with stop-at-first-match semantics - Add heuristic_departure_signal field to predeparture prompt, exposing the pre-computed departure model output (covers theta_r, urgency decay via theta_u/gamma, low-confidence precaution, and neighbor departure pressure) THETA_TRUST LLM ENFORCEMENT (predeparture + routing prompts): - When theta_trust=0.0: strip inbox entirely, add BINDING CONSTRAINT instructing LLM to IGNORE all neighbor/social data - When theta_trust>0.0: inject calibrated percentage guidance (e.g., "rely 70% on own observation, 30% on neighbor messages") - Apply _consider_pol, _belief_weigh_pol, trust_policy to all 3 routing prompt locations (destination, route, and predeparture) SCENARIO-AWARE HISTORY: - Filter agent_self_history through filter_history_for_scenario() before embedding in routing prompts (prevents data leakage from historical records) SPATIAL MESSAGING: - Add COMM_RADIUS_M env var for distance-based broadcast filtering - Precompute SPAWN_EDGE_MIDPOINT for pre-departure agent positions - Pass agent positions to messaging.begin_round() for spatial delivery - Include comm_radius_m in messaging config sections of all prompts CONFIGURATION: - Remove inline AgentMessagingBus/OutboxMessage (now imported) - Widen lambda_e bounds to (0.0, 100.0) and lambda_t to (0.0, 100.0) - Add fire source F0_8 at (16348, 6801) with r0=400 - Export fire_sources and fire_events to run parameter log Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Functional updates: - Disable veh3 and veh4 spawn groups (commented out) to reduce toy-model agent count for focused testing - Comment out large-scale spawn groups (veh9–veh41) — reserved for future 100+ agent experiments - Update SUMO network (Repaired.net.xml): add junction J20 and associated internal edges for improved routing near south zone - Update Repaired.netecfg and Repaired.sumocfg timestamps Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Move hardcoded fire sources, destinations, routes, and spawn events from
Python source into JSON config files under configs/<map>/. Add --map CLI
flag (default: lytton) so switching networks requires no code changes.
Add compact spawn format: {"edge": "...", "count": N} auto-generates
agent IDs from edge names, staggers positions within edge bounds, and
cycles colors. Position overflow is validated against actual SUMO edge
lengths after network load.
Also includes risk_density normalization (edge-count invariance) with
5 new tests, and enables veh3/veh4/veh9 spawn groups in spawn_events.py.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Resolve conflicts by keeping local (branch) versions which include config externalization, compact spawn format, and risk_density normalization changes. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…d logging Add configs/halifax/ with network paths, 4 shelters, 3 fire sources, and 38 spawn groups. Include Halifax SUMO config files (net.xml and buildings.xml excluded via .gitignore due to size). Add scripts/generate_spawns_from_buildings.py: offline tool that reads building polygons, finds nearest drivable edges via KD-tree, and writes spawns.json in compact or detailed format. Supports --mode per-building and per-edge with configurable --count, plus SUMO XY --bbox filtering. Record SUMO_SEED in run_params JSON for reproducibility. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Track input/output/total tokens and LLM call count across all four OpenAI call sites using a thread-safe accumulator. Results are included in run_metrics JSON output. Also adds total_agents count and --map flag to experiment runner. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Splits the previously-uniform information channel into two streams: - Environmental signals (personal observation) are now always real-time; the noise model still applies but `apply_signal_delay` is no longer used on the env path. This better reflects that drivers see what's around them immediately, regardless of broadcast lag. - Institutional channels (forecast, annotated route/destination menus, advisory labels, expected-utility scores) are subject to `INFO_DELAY_S` via a new `apply_institutional_delay` resolver and a new `institutional_history` ring on each `AgentRuntimeState`. When history is shorter than the delay, the agent receives a `no_notice`-grade view on the institutional channel for that round, modeling the real-world lag before the first official report arrives. In `no_notice` mode the institutional channel is already invisible, so the delay is a no-op. Wired through all four LLM decision sites in main.py (predeparture routing, departure-destination, in-transit destination, in-transit route). Also expands `_run_parameter_payload` with control_mode, decision_period_s, openai_model, max_concurrent_llm, net_file, sumo_cfg, and new agent_memory, forecast, and overlays sections so sweep artifacts capture the full runtime configuration. Bumps `MAX_CONCURRENT_LLM` default 20 -> 50. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Pass --params-log-path to each subprocess so every sweep run writes its own run_params_<case_id>.json alongside metrics_<case_id>.json. Without this, downstream plot scripts had no way to recover the scenario / sigma / delay / trust metadata for completed runs and fell back to "unknown". Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
plot_experiment_comparison.py: - Filter out *_profiles.json siblings from --metrics-glob so the per-agent cognition dump no longer pollutes load_cases with all-zero rows. - Add a filename-parser fallback in _param_metadata that recovers scenario / sigma / delay / trust from the metrics filename when no run_params companion is present (older runs). - Promote the scenario palette to module-level SCENARIO_COLORS / SCENARIO_ORDER constants so other plot scripts can reuse them. plot_run_metrics.py: - Add a --metrics-glob flag and a new plot_kpi_multirun() that draws a 2x2 KPI grid (departure variance, route entropy, hazard exposure, avg travel time) with one bar per run, sorted contiguously by scenario, colored by scenario, with a shared legend. The single-run dashboard path is unchanged. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Building-grouped spawn manifest for the Halifax map, keyed by edge id with per-edge agent counts. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Implements the timed-alert reconstruction of the 28 May 2023 Upper Tantallon wildfire evacuation, decomposed into the build-plan modules. - M0, the two-clock fix, DECISION_PERIOD_S=240 with a SIM_STEP_LENGTH_S constant, and a per-source fire radius cap via max_r_m. - M1, alert_schedule.py resolves a timed, area-scoped alert schedule so the information regime becomes per-agent and per-time. config_loader loads alerts.json and ALERT_TIME_OFFSET_S drives the E1 timing arm. - C.7, belief-only compliance. An evacuate order blends into belief through theta_auth times a channel factor rather than a mandatory prompt rule, and rule_based_policy.py mirrors the LLM path. - M2, staggered awareness. An agent stays dormant until a signal reaches it via alert, door knock, perception, or peer, so the urgency clock starts at awareness. - M3, door-to-door as a live driver, a door-knock awareness trigger and an in-person belief channel through DOOR_CHANNEL_FACTOR, plus the per-run consolidated timeline export in run_timeline.py. - Part J metrics, mobilization delay, order compliance by channel and area, area clearance, awareness-source share, corridor flow, and the non-evacuee fire-reach companion count. - E0 config under configs/halifax_3town_e0 and the E0/E1/E4 experiment driver scripts/run_experiments.py. 473 tests pass. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Adds the outcome measure the existing metrics were missing, lets a household be measured at its own building instead of its street, and removes the per-step TraCI traffic that dominated every run. Time margin reports the gap between a household leaving and the fire reaching its home, so a run has a consequence number even where nobody is caught. Fire arrival is interpolated against the previous sample rather than quantised to the 240 s round, and homes the fire never reaches fall back to the closest approach. Households fall into cleared, caught_at_home, never_threatened, or never_departed_safe. The home a household is measured at follows a geometry basis. Configs carrying home_xy building centroids resolve per household, everything else keeps its spawn edge and is bit-identical to before. The basis travels in the metric output and the run params so the two experiment batches can never be pooled. Per-step vehicle state moves onto TraCI subscriptions. Position, angle, edge, and route were each read twice per vehicle per step, seven round trips in total, now served by one call. The per-step stdout log is off by default, since it reached 44 MB for a one-hour run. Fire polygons are drawn only under a GUI binary and only when the radius has actually moved. Measured on an 1800 s run: 1,750,605 TraCI calls to 109,959, and a 3600 s run from 194 s to 102 s wall clock with a byte-identical metrics summary. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
The spawn generator snapped a building to whichever edge had the nearest middle vertex, which put a house near the end of a long street onto a different street whose midpoint happened to be closer. Snapping now measures to the edge polyline with the same polygonOffsetAndDistanceToPoint call the hazard model uses, so an authored package and the simulation agree on where a household sits. Pass --snap midpoint to reproduce a config authored before this. Households no longer spawn on a motorway, motorway link, trunk, or trunk link. Passenger cars are allowed on all of them, so drivability alone was never the right test, and a driveway does not meet a limited-access highway. A building whose nearest road is one of those is matched to the nearest community street, and left unsnapped when there is none in range. --allow-highway-spawn restores the old behaviour. --attach-centroids-to holds an existing spawn set fixed and only attaches building geometry, so a centroid config is the same household population as the edge config it derives from and the two batches stay comparable. Assignment runs in two passes over a global claimed set, so one building never becomes two households. Two new configs, neither replacing anything. halifax_3town_e0_centroid was built with the midpoint snap, halifax_3town_e0_centroid_exact with the polyline snap. Both carry the same 45 edges and 182 households as halifax_3town_e0, with 182 distinct buildings and no edge fallbacks. The exact one is the one to run. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
The console wraps the simulator without modifying it, running the simulation script as it is through a launcher that attaches a read-only bridge between TraCI steps. Three views cover configuring a run, watching it, and reviewing it. Adds authoring. An operator draws a box on the map, the buildings inside become households, a second selection becomes the area an order covers, and fire origins are placed by click with a scrubber showing the front at a chosen instant. A fourth tool sets one building's agent count, since most buildings are houses holding one vehicle while a school or a care home holds many. Buildings are the unit of selection because that is what an operator and the record both name, and edges are the unit the simulator inserts on, so the translation happens once when the package is written. That resolved the building-level alert areas without touching agentevac/, since alerts.json keeps the edge format the alert engine already reads. An alert area is a strict subset of the households, enforced in the selection, the view, and the backend. A building holding no agents cannot be evacuated, and including it would pull its road into the ordered area and order households that were never selected. The write path creates a package directory or does nothing. A name already under configs/ is refused with 409, a failure part way through removes what was written, and no code path opens an existing package file for writing. Map bundles gained a building layer carrying each building's centroid, footprint, simulation coordinates, and the road a household there would spawn onto. Simulation coordinates needed a longitude and latitude to UTM transform, which sumolib cannot do without pyproj, so the series implementation in ui/bridge/projection.py now runs both directions. It round-trips within 10 mm across three UTM zones and agrees with sumolib plus pyproj to 64 mm on 182 real buildings. Also adds a Quit control, which ends a run in flight so it exports through its own finally block, then stops the console and releases its port. configs/westwood_uitest is the package authored during browser verification, 175 buildings and 821 agents. Safe to delete. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Uncommitted changes that predate the console work and travel with it. The halifax_3town_e0 shelter list moves from the placeholder Shelter_A to D onto the three real destinations the runs already use, run_experiments gains sweep flags, and paper/ is ignored. Co-Authored-By: Claude Opus 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.
Two bodies of work. The Halifax reconstruction modules, which turn the domain-expert
exchange into a runnable E0 substrate, and an operator console that wraps the simulator
without modifying it and lets a scenario package be authored by drawing on a map.
Halifax reconstruction
alerts.json, resolvedper agent and per instant, so the information regime becomes a property of where a
household is and what has been issued.
rule removed, so an order enters through belief and not as a switch.
urgency clock starts at that instant rather than at t=0.
per-run timeline covering ignition, alerts, awareness, departure, arrival, and
clearance.
clearance, corridor flow, and the non-evacuee fire-reach companion count.
DECISION_PERIOD_Smoved to 240 s against a 0.2 s integration step,guarded so a decision round is always a whole number of SUMO steps.
Time margin, the outcome measure that was missing
Every arm reported 182 of 182 arrived and zero fire contact, at the historical timing and
with every alert delayed an hour alike, so nothing measured the cost of being late.
Time margin reports the gap between a household leaving and the fire reaching its home.
Fire arrival is interpolated against the previous sample rather than quantised to the
240 s round, and homes the fire never reaches fall back to the closest the fire came, so
a run has a number either way. Households resolve to
cleared,caught_at_home,never_threatened, ornever_departed_safe.Building-centroid hazard basis
Hazard distance was measured to the spawn edge polyline, so every household on a street
inherited the exposure of its most exposed corner. Configs carrying
home_xybuildingcentroids now resolve per household. Everything else keeps its spawn edge and is
bit-identical to before, and the basis travels in the metric output and the run params so
the two experiment batches can never be pooled.
Two new configs, neither replacing anything.
halifax_3town_e0_centroidandhalifax_3town_e0_centroid_exactboth carry the same 45 edges and 182 households ashalifax_3town_e0. The exact one is the one to run.Snapping correctness
Building-to-edge matching measured to the nearest middle vertex, which put a house near
the end of a long street onto a different street. It now measures to the edge polyline
with the same call the hazard model uses.
Households also no longer spawn on a motorway, motorway link, trunk, or trunk link.
Passenger cars are allowed on all of them, so drivability alone was never the right test.
A building whose nearest road is one of those is matched to the nearest community street.
Runtime
Position, angle, edge, and route were each read twice per vehicle per step. They now
arrive on one TraCI subscription call per step. The per-step stdout log is off by
default, and fire polygons are drawn only under a GUI binary.
Measured on an 1800 s run, 1,750,605 TraCI calls to 109,959. A 3600 s run went from 194 s
to 102 s wall clock with a byte-identical metrics summary.
Operator console
Runs the simulation script as it is, through a launcher that attaches a read-only bridge
between TraCI steps. The bridge issues no TraCI command and changes no simulation
variable, and
ui/tests/test_run_parity.pyproves the trajectory is unchanged. Consoleruns land in
outputs/ui_runs/so they cannot sit beside a research campaign. Thebackend is standard library only, so nothing is added to the environment the simulator
runs in, and the built interface needs no network at any point.
Authoring. An operator draws a box, the buildings inside become households, a second
selection becomes the area an order covers, and fire origins are placed by click with a
scrubber showing the front at a chosen instant. A fourth tool sets one building's agent
count, since most buildings hold one vehicle while a school or a care home holds many.
Buildings are the unit of selection because that is what an operator and the record both
name, and edges are the unit the simulator inserts on, so the translation happens once
when the package is written. That resolved building-level alert areas without touching
agentevac/.An alert area is a strict subset of the households, enforced in the selection, the view,
and the backend. A building holding no agents cannot be evacuated, and including it would
pull its road into the ordered area and order households that were never selected.
The write path creates a package directory or does nothing. A name already under
configs/is refused with 409, a failure part way through removes what was written, andno code path opens an existing package file for writing.
Review notes
agentevac/simulation/main.pycarries the time-margin wiring, the centroid basis, andthe TraCI batching together, because they cannot be separated by file.
VEHICLE_STEP_LOG=1.configs/westwood_uitestis a package authored during browser verification, 175buildings and 821 agents. Safe to delete.
ui/assets/previews/are generated and gitignored. Build them withpython -m ui.tools.build_map_assets, about 20 s per package.Verification
672 Python tests pass with 4 skipped, 85 frontend tests pass, typecheck clean, production
build succeeds. The parity test is opt-in behind
AGENTEVAC_UI_SLOW_TESTS=1since itstarts SUMO twice.
The authoring path was checked end to end against a live backend, and the whole interface
was walked through in a browser.
🤖 Generated with Claude Code