goatifi / docs /SPEC_AUDIT.md
KonoDioDaa's picture
Initial FlowTwin deployment
e7a9f02
|
Raw
History Blame Contribute Delete
11.1 kB

A newer version of the Gradio SDK is available: 6.24.0

Upgrade

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.pybenchmarks/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