Spaces:
Runtime error
Runtime error
| # Specification audit | |
| Every requirement from the two project documents and the build brief, checked | |
| against what is actually in the repository. Where something is partial or | |
| deliberately not built, it says so. | |
| Legend: **✓** built and verified · **◐** partial, scoped deliberately · **✗** not built | |
| --- | |
| ## Core loop — SEE → PREDICT → SIMULATE → ACT | |
| | Requirement | Status | Where | | |
| |---|---|---| | |
| | Observe current crowd state | ✓ | `crowd/state.py` — occupancy, density, inflow, outflow, velocity, utilisation, growth, conflict, risk | | |
| | Predict near-term state | ✓ | `prediction/` — trained model + physics baseline, +30/60/90/120 s | | |
| | Simulate candidate interventions | ✓ | `strategy/counterfactual.py` — each candidate on an identical clone | | |
| | Act: recommend and apply | ✓ | `strategy/optimizer.py`, `strategy/engine.py`; operator applies from the UI | | |
| | Observe again — closed loop | ✓ | applying feeds the same simulation; benchmark arm re-reviews on a cycle | | |
| ## Simulation | |
| | Requirement | Status | Notes | | |
| |---|---|---| | |
| | Individual agents | ✓ | Structure-of-arrays; 40,000 in the showcase run, 78,000 in Barcelona | | |
| | Origins, destinations, movement, velocity | ✓ | Per-agent speed factor from a clipped normal | | |
| | Routes and route preferences | ✓ | Next-hop tables per policy; three policies | | |
| | Reroute compliance | ✓ | Per agent, sampled per scenario; instructions are refused by some | | |
| | Congestion | ✓ | Weidmann speed–density, evaluated per ~12 m cell | | |
| | Capacity constraints | ✓ | Node service rate and edge throughput, both with fractional carry | | |
| | Changing infrastructure capacity | ✓ | Scripted timeline events; retunable from the What-If panel | | |
| | Event phases | ✓ | Venue phases drive the phase label; scenarios carry a phase timeline | | |
| | Rerouting | ✓ | Adaptive policy adoption with per-agent compliance | | |
| | Visible bottlenecks | ✓ | Verified in the browser and asserted in tests | | |
| | Deterministic seeds | ✓ | RNG state travels with the snapshot; asserted in tests | | |
| | Accelerated execution | ✓ | 1× … 40× | | |
| | 10,000–40,000 agents | ✓ | ~2–4 ms per step at 40,000 | | |
| ## Crowd State Engine | |
| Occupancy, density, inflow, outflow, velocity, capacity utilisation, density | |
| growth, queue growth, risk score — **✓** all present, plus opposing-flow conflict | |
| and peak local density. Per-term risk contributions are exposed so alerts can | |
| explain themselves. | |
| ## Prediction | |
| | Requirement | Status | Notes | | |
| |---|---|---| | |
| | Genuine prediction layer | ✓ | Gradient boosting, one model per horizon | | |
| | Uses actual simulation state | ✓ | Features come from the Crowd State Engine only | | |
| | "Where will congestion develop in 30/60/90 s" | ✓ | Plus 120 s | | |
| | Strong baseline first, model swappable | ✓ | Analytic mass-balance projection; model used only if it beats it on held-out seeds | | |
| | No faked ML | ✓ | Validation on disjoint seeds, reported in the UI | | |
| ## Hugging Face | |
| | Requirement | Status | Notes | | |
| |---|---|---| | |
| | Genuine integration | ✓ | `perception/huggingface.py`, real inference path | | |
| | Camera → HF model → observation → crowd state | ✓ | Shared observation schema | | |
| | Both modes converge | ✓ | `observation_to_zone_state` | | |
| | Documented model choice | ✓ | Candidate chain with the two specification models first; manifest written on load | | |
| | Never fabricates a count | ✓ | Reports the real error instead; asserted in tests | | |
| **Caveat, stated plainly:** the build environment had no network access to | |
| `huggingface.co`, so the chain could not be exercised against live weights here. | |
| The code path, the CSRNet architecture, the manifest and the failure reporting | |
| are all implemented and the endpoint is verified to fail honestly when no model | |
| loads. Run `scripts/fetch_hf_model.py` on a networked machine to download, | |
| select and verify with a real inference. | |
| ## Strategy engine | |
| | Requirement | Status | | |
| |---|---| | |
| | Generates candidate interventions | ✓ | | |
| | No action / reroute % / gate stagger / alternate exit / destination split | ✓ | | |
| | Combined interventions | ✓ | | |
| | Set depends on venue topology | ✓ — a reroute needs an alternative path; an alternate exit needs measured spare capacity | | |
| ## Counterfactual simulation | |
| Capture state → clone → apply A → simulate → reset → apply B → … → compare → | |
| select. **✓** Implemented exactly, with tests asserting that two branches of one | |
| state produce identical results and that evaluation does not advance the live | |
| run. | |
| ## Optimization | |
| Peak density, critical duration, average travel time, queue, throughput, | |
| aggregate risk, unnecessary rerouting — **✓** all seven in `J`, weights | |
| configurable by environment variable, contributions exposed per strategy. | |
| Explanation generated from the same normalised terms that produced the score. | |
| ## Dynamic routing | |
| | Requirement | Status | | |
| |---|---| | |
| | Not static shortest path | ✓ | | |
| | Cost responds to distance, travel time, congestion, density, capacity, risk | ✓ | | |
| | Oscillation prevention | ✓ — hysteresis, policy stickiness, cycle-break, asserted in tests | | |
| | Rerouting produces observable change | ✓ — verified in the browser and in tests | | |
| ## Simulation 1 — F1 Circuit Stress Test | |
| Fictional venue with 4 gates, 6 spectator zones, 8 concourse corridors, 4 exits, | |
| 3 concessions, 2 transport hubs — **✓**. Large post-race crowd, simultaneous | |
| egress, reduced exit capacity — **✓**. The full arc (normal flow → bottleneck → | |
| prediction → strategy evaluation → recommendation → rerouting → recovery) runs | |
| end to end without manual intervention and is verified by `scripts/ui_check.py`. | |
| ## Simulation 2 — Barcelona 2022 | |
| | Requirement | Status | | |
| |---|---| | |
| | Simplified digital twin of the spectator/transport network | ✓ | | |
| | Circuit, spectator zones, gates, pedestrian routes, exits, parking, transport | ✓ | | |
| | Historical facts separated from assumptions | ✓ — two labelled lists, on screen, each fact with a source | | |
| | Explicit counterfactual disclaimer | ✓ — in the venue data, the briefing and the UI | | |
| | No claim of reproducing telemetry | ✓ — asserted in tests | | |
| ## Frontend | |
| Race Control dashboard with event, crowd state, venue map, density, predicted | |
| bottlenecks, alerts, flow direction, simulation status and recommendation — **✓**. | |
| Crowds move; congested zones change colour; routes animate; predicted congestion | |
| is drawn distinctly from current congestion. Strategy simulator with measured | |
| outcomes and a recommended row — **✓**. Explainability panel using actual | |
| calculated values — **✓**. | |
| ## Backend & real-time | |
| FastAPI, modular packages (simulation / crowd / prediction / routing / strategy / | |
| perception / api), WebSocket streaming with no per-frame polling, graceful | |
| validation failures — **✓** all present, with API tests covering the failure | |
| modes. | |
| ## Evaluation | |
| Baseline shortest-path, baseline static routing and FlowTwin compared across | |
| multiple seeds with mean ± standard deviation, generated automatically — | |
| **✓** `scripts/run_benchmarks.py` → `benchmarks/BENCHMARKS.md`. No number is | |
| entered by hand. | |
| ## Demo reliability | |
| Precomputed recordings replay through the same interface — **✓** | |
| `scripts/record_fallback.py`, `ReplaySession`. The live path is always primary. | |
| --- | |
| ## Deliberately not built | |
| These come from the wider master proposal rather than the P0 list in the build | |
| brief, and were left out rather than half-built: | |
| | Item | Why | | |
| |---|---| | |
| | **Safety / compression mode as a separate mode** | ◐ The compression-risk proxy itself *is* implemented — the risk score combines density, density growth, velocity drop, queue growth and opposing flow exactly as the proposal specifies, and alerts surface those causes. What is not built is a separate in-event concert scenario and a distinct "safety mode" UI. | | |
| | **Personnel dispatch engine** | ✗ Security/medical resources, dispatch scoring and their map layer are not implemented. It is P1 in the proposal and absent from the brief's P0 list. | | |
| | **Natural-language assistant** | ✗ P2, and explicitly excluded from the decision loop by design. | | |
| | **Redis / PostgreSQL** | ✗ Deliberate. See `ARCHITECTURE.md` §10. | | |
| | **Next.js frontend** | ◐ Traded for a zero-build single-page console served by the backend. Rationale in `ARCHITECTURE.md` §8. | | |
| | **Multi-camera fusion, venue editor, city-scale transport** | ✗ P2. | | |
| ## Defects found and fixed during this audit | |
| Recorded because they are the difference between a demo that looks right and a | |
| model that is right. | |
| | Defect | Symptom | Fix | | |
| |---|---|---| | |
| | Density averaged over a whole corridor | A queue at one gate slowed everyone in the corridor, including people 200 m back with clear space; throughput collapsed to a tenth of the real value | Density and speed evaluated per ~12 m cell | | |
| | Links accepted people at capacity until physically full | Corridors silently absorbed impossible numbers instead of pushing congestion upstream | Backward-wave receiving function — a link stops accepting before it is full, so congestion spills back | | |
| | Queue extent measured only at the stop line | The standing queue occupied almost no length, so people had to walk *through* a near-jammed corridor to reach it, throttling a 500/min gate to under 200/min | Queue extent measured from everyone who has actually stopped | | |
| | Routes cut straight through grandstands | Shortest paths used seating bowls as shortcuts, deadlocking against the people trying to leave them; the Barcelona venue gridlocked with 18,000 people stranded | A route may start or end at a stand, never transit one | | |
| | Agents U-turning in corridors | After repeated interventions a residue bounced between two nodes and never arrived | Reversing onto the corridor just walked is refused unless it is the only option | | |
| | Intervention penalties compounded without limit | Repeated operator action permanently distorted the cost surface | Penalties are capped and relax back towards neutral each refresh | | |
| | What-If capacity slider sent an empty override | A control that appeared to work and did nothing | The slider now retunes the scripted timeline event itself | | |
| | Alert cards rebuilt on every frame | Entry animation restarted 5×/second, leaving the alert panel permanently mid-fade and effectively invisible | Cards keyed on structure; live values written in place | | |
| | Orphaned sessions kept simulating | A refreshed browser tab starved the event loop and new runs appeared to hang | Sessions with no subscribers idle and are reaped | | |
| | Model inference pinned to two threads | A 66-row inference took 1,000 ms instead of 9 ms | BLAS/OpenMP thread pools pinned at import | | |
| ## Verification performed | |
| - `backend/tests/` — 70 tests across simulation, intelligence and API | |
| - `scripts/ui_check.py` — drives the full acceptance path in a real browser, fails on any console error or failed request | |
| - `scripts/run_benchmarks.py` — multi-seed quantitative evaluation | |
| - `scripts/train_predictor.py` — held-out validation of the predictor | |