Inspiration

After a flood, an emergency operations centre is buried in field reports that contradict, refine and repeat each other: "CR-14 bridge open to light vehicles", then "no heavy vehicles", then a caller who "heard the north bridge might be closing?", then an engineer saying the span shifted.

The room has one narrow, urgent question: with the crews, money and hours we have, which repair restores the most access, and does that answer still hold after the latest report? Today that's answered on whiteboards and memory, and two things go wrong:

  1. State drifts. Nobody can say what the current condition of each crossing is, or which report that belief rests on.
  2. Consequences are guessed. "Fix the bridge" feels right, but whether it beats a 12-hour temporary crossing depends on network topology, what else is closed, the budget and how long each option takes.

ASTER is built to fix both.

What it does

ASTER keeps an incident's operational memory in Evorozen Neural Pulse, reconstructs the current condition of every bridge, culvert and road from messy and conflicting reports, and recomputes the best repair plan after every report.

  • Overview: the situation in four numbers, one button ("What should we fix?"), and an answer: the intervention, properties reconnected, facilities that regain an ambulance route, cost, duration, and why. Changing budget, time window, crews or planning horizon recomputes it instantly.
  • Live state: type a report the way it would be radioed in and watch it travel through every pipeline stage, with each Neural Pulse call, status and timing shown. Ambiguous references ("The bridge is shut.") wait for a person to choose, and that choice is saved to Pulse as a learned alias.
  • Interventions: every option evaluated against the live network and ranked, with the reason each excluded option was excluded.
  • Evidence: for every piece of infrastructure, its status, confidence, the reports it rests on, the reports that were superseded, and its full history.

Example, from the engine on our synthetic Harlan Valley flood (1,350 properties): after an engineer reports the County Road 14 bridge closed, 790 properties are cut off. ASTER recommends repairing the bridge (+680 properties reconnected, $180K, 2 days). Cap the budget at $50K and it switches to a $40K, 12-hour temporary crossing. Report the bridge damaged and the standard repair goes out of scope, while the $1.25M, 21-day replacement ranks only 4th.

How we built it

Neural Pulse is the memory of the incident, not a decorative API call. We use it as:

  • the system of record (five tables: incidents, aliases, observations, entity state, transitions)
  • an append-only evidence ledger where nothing is ever deleted
  • the materialized current state, with drift detection against our own re-fold
  • semantic entity resolution through vector_search, so "the crossing over Harlan Creek on 14" matches CR14-BRIDGE
  • memory that learns, by saving human-resolved aliases
  • report interpretation through its chat action, validated as strict JSON

Deterministic core, AI at the edges. Language is messy, so interpretation and matching use Pulse. Everything that produces a number the decision depends on is deterministic, explainable and tested.

State reconstruction. Reports are folded in time order, with sources ranked engineer > EMS/field crew > public. A firm report supersedes disagreeing evidence. A hedged or lower-ranked contradiction makes the link Uncertain instead of winning. Damage is sticky, and the network engine treats uncertain links as closed.

Network engine. A road graph of 31 nodes and 36 links. Reachability from the county seat is computed per vehicle class by breadth-first search. The access score is

$$A(S) = \sum_{p} n_p \sum_{c} w_c \, \mathbf{1}[\,p \text{ reachable by class } c \text{ in state } S\,]$$

where \( n_p \) is the property count at settlement \( p \) and the weights are \( w_{\text{car}} = 0.5 \), \( w_{\text{ambulance}} = 0.3 \), \( w_{\text{truck}} = 0.2 \).

Exact optimizer. Interventions are few, so we enumerate every feasible combination up to the crew count and score each with the full network engine. That captures synergy (two repairs in series) and redundancy (two repairs reconnecting the same area). Each plan \( P \) is scored by a time-weighted recovery value

$$V(P) = \Delta A(P) \cdot \frac{T - d(P)}{T}$$

where \( \Delta A(P) \) is the access gained, \( d(P) \) the plan's duration and \( T \) the planning horizon. Access restored sooner counts for more, so a three-week replacement is worth little over a 72-hour horizon. The optimum is

$$P^{*} = \arg\max_{P} \, V(P) \quad \text{subject to } \textstyle\sum_{i \in P} c_i \le B, \; |P| \le k, \; d(P) \le W$$ where \( c_i \) is the cost of intervention \( i \), \( B \) the budget, \( k \) the number of crews and \( W \) the time window.

With under 16 interventions and at most 4 crews that is only a few thousand combinations, so we evaluate all of them and never wonder whether a greedy ranking missed a better plan. A fixed enumeration order and a full tie-break make results byte-identical for the same state.

Stack: Next.js (App Router), React, TypeScript, Zod, Vitest, deployed on Vercel. The engine is pure TypeScript and runs on both the server and the browser, so constraint changes recompute instantly.

Challenges we ran into

  • The live API didn't always match its docs. The OpenAPI spec says updates, but the live service needs filter and changes. It rejects data actions without a non-empty prompt. It also returned duplicated and altered copies of rows after updates. We wrote npm run pulse:probe to check the real contract, de-duplicate every read, and treat the ledger as append-only.
  • Ranking by access alone gave a bad answer. Early versions recommended a 21-day, $1.25M replacement over a 12-hour temporary crossing. The horizon-weighted recovery value fixed that, and it's exposed to the user as a control.
  • Never guessing on ambiguity. Resolution auto-accepts only a confident, clearly leading match. Otherwise the report is recorded but changes nothing until a person picks.
  • Quota and failure handling. The app rotates across multiple keys, never retries limit errors, and if Pulse is unreachable it shows a clearly labelled Cached demo state and pauses reporting. It never invents a Pulse response.

Accomplishments that we're proud of

  • Every number on screen is computed by the engine, never written by an LLM, and is traceable to specific reports.
  • Exact optimization across every combination of repairs, plus a visible state hash for reproducibility.
  • Honest boundaries: we document what Pulse does and what ASTER's own logic does.
  • 55 passing tests covering the fold rules, optimizer, key handling, live-contract rules and the full pipeline, plus a labelled, graceful fallback mode.
  • Per-visitor incidents, so judges never overwrite each other.

What we learned

  • Use AI where language is messy and keep deterministic code where decisions and numbers matter.
  • A memory layer is only trustworthy if it is append-only and you can explain every state from the evidence.
  • Time matters in recovery: the fastest useful fix often beats the best final fix.
  • Probe the real API early, because documentation and live behaviour can differ.

What's next for Aster

  • Replace the synthetic Harlan Valley data with a real road network (for example from OpenStreetMap) and costed intervention catalogues.
  • Model crew skills and equipment, and make worsening damage raise repair cost instead of only taking it out of scope.
  • Run pilots with county emergency operations centres and public-works teams, the people who make this decision today.
  • Add multi-incident support, radio and SMS intake, and exportable situation reports for after-action review.

Code: https://github.com/Abdullah49645/aster *Live Demo: * https://aster-ten-kohl.vercel.app/

Built With

  • climate
  • css
  • emergency-management
  • evorozen-neural-pulse
  • graph-algorithms
  • nextjs
  • node.js
  • optimization
  • react
  • typescript
  • vector-search
  • vercel
  • vitest
  • zod
Share this project:

Updates

Submission history