DEV Community

Amrita Yadav
Amrita Yadav

Posted on

ForkTrace: following a food outbreak back through a graph

Ten people get food poisoning. They ate at different restaurants, on different days. Is it a coincidence, or did their food come from the same place?

I'm a third-year engineering student from India, and that question turned into my project for Graph Hacks 2026. I called it ForkTrace: "follow the fork back to the farm."

The tricky part is that no single record answers it. A sick person's report doesn't name a food batch. A shipment record doesn't say who ate what. The answer only shows up when you follow the links: the person, the meal, the batch, the shipment, the restaurant. That is a graph problem, so I built the whole thing on FalkorDB. All the data is synthetic and comes from a fixed random seed, so every run gives the same result.

Here is what ForkTrace does. It ranks the batches that could be the source. For each one, it shows the exact path of records that points to it. It finds every place and product a batch reached, and it proposes a recall that a human has to approve. When someone approves, the recall gets saved back into the graph as its own record.

Two kinds of evidence

This is the part I care about most. Some meals have a kitchen log that says exactly which batch was used. I call that recorded evidence. For other meals I can only guess: the restaurant received a batch of that ingredient and it was still fresh on that day. That is inferred evidence, and it only counts for half.

This is the query behind the inferred part:

MATCH (m:Meal)-[:CONTAINS]->(i:Ingredient)<-[:OF]-(b:Batch)
      <-[:CARRIES]-(s:Shipment)-[:DELIVERED_TO]->(r:Restaurant)
      <-[:SERVED_AT]-(m)
WHERE s.day <= m.day AND m.day <= s.day + b.shelf
  AND NOT (m)-[:SERVED_BATCH]->(:Batch)-[:OF]->(i)
Enter fullscreen mode Exit fullscreen mode

The last line is important. If a meal already has a recorded batch for an ingredient, I never guess a different batch for it. My first idea was simpler: if a restaurant got a batch and the meal had that ingredient, blame the batch. That would have wrongly blamed every batch the restaurant received, so I changed it.

In my demo data, the spinach batch SP-2041 ranks first. But the tomato batch is close behind, because tomato is in the same salads. The lead is only about 1.6 times the runner-up, so ForkTrace says "medium confidence" and calls SP-2041 a leading candidate, never a proven cause. It would have been easy to make the tool sound more sure than it is. I didn't want that.

Real data is also messy, so I built a demo for it. I delete one shipment record, SP-2041 going to restaurant R3. The kitchen logs still say that batch was served at R3. The recorded evidence stays, the inferred evidence drops, and ForkTrace flags a conflict and keeps R3 on the review list. A missing record gets surfaced instead of hidden.

To check my numbers, I wrote a tiny pure-Python version of the same calculations. It reads only the raw data file. My tests compare what FalkorDB returns against it, so no expected number is typed in by hand. All 40 tests pass.

What went wrong

Docker wasn't installed on my PC, so my database tests failed at first and I moved to FalkorDB Cloud. My first Vercel deploy failed too, because I had moved my folders to the repo root and forgot to update the root directory setting. I also found out that FalkorDB doesn't support WHERE NOT EXISTS { MATCH ... }, so I rewrote that check using OPTIONAL MATCH and a count.

What it is not

ForkTrace is a prototype on made-up data, not a real food-safety tool. The pipeline is fixed code, not an LLM choosing tools, and I didn't use one of FalkorDB's built-in graph algorithms. Those are the first two things I want to add next: an agent that picks between the query tools, and something like shortest path or centrality across the supply network.

I used Gemini for coding help, and ChatGPT and Claude for planning and review. I went through the code and I can explain every query.

What I learned: the graph model mattered more than the interface. Once the relationships were right, the evidence paths and even the conflict check came almost for free from Cypher. And being honest about uncertainty made the tool better, not weaker.

Code: https://github.com/amuisaddiction/forktrace
Live demo: https://forktrace-forktrace.vercel.app

Top comments (0)