<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Harsh Rastogi</title>
    <description>The latest articles on DEV Community by Harsh Rastogi (@harshrastogii).</description>
    <link>https://dev.to/harshrastogii</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F4187933%2Ff5a70356-8c48-4e34-a6e2-88daa393e48f.png</url>
      <title>DEV Community: Harsh Rastogi</title>
      <link>https://dev.to/harshrastogii</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/harshrastogii"/>
    <language>en</language>
    <item>
      <title>How I built a repair triage system for remote public housing, and why I hide the model's confidence from tenants</title>
      <dc:creator>Harsh Rastogi</dc:creator>
      <pubDate>Fri, 16 Oct 2026 05:54:38 +0000</pubDate>
      <link>https://dev.to/harshrastogii/how-i-built-a-repair-triage-system-for-remote-public-housing-and-why-i-hide-the-models-confidence-2dh1</link>
      <guid>https://dev.to/harshrastogii/how-i-built-a-repair-triage-system-for-remote-public-housing-and-why-i-hide-the-models-confidence-2dh1</guid>
      <description>&lt;h1&gt;
  
  
  How I built a repair triage system for remote public housing, and why I hide the model's confidence from tenants
&lt;/h1&gt;

&lt;p&gt;  &lt;iframe src="https://www.youtube.com/embed/pv9izNCmHDo" width="710" height="399"&gt;
  &lt;/iframe&gt;
&lt;/p&gt;

&lt;h2&gt;
  
  
  1. The problem
&lt;/h2&gt;

&lt;p&gt;A family in a remote Northern Territory community loses water to their house. They ring the repairs line. In Darwin, a plumber would usually be there within a couple of days. Out bush, the same repair can sit for weeks.&lt;/p&gt;

&lt;p&gt;The reason is arithmetic. Sending a tradesperson out to a remote community for a single job costs a fortune, so remote jobs get bumped. In town, urgent repairs get done in days. Remote, the same job waits weeks. This is the gap ReachNT was built to close: a repair triage system for remote NT public housing that ranks repairs fairly and plans trips smart.&lt;/p&gt;

&lt;p&gt;Aashish and I built it as Team Top Enders for the CDU IT Code Fair 2026 AI Challenge. It is a working demo, built for a uni challenge, and I will be upfront about its limits throughout this post. The system reads tenant repair reports, ranks them by need, batches neighbouring communities into shared weekly trips, and gives every tenant a plain-English explanation of why their repair waited as long as it did.&lt;/p&gt;

&lt;h2&gt;
  
  
  2. The data we had and the data we didn't
&lt;/h2&gt;

&lt;p&gt;No public NT work-order dataset exists. That is the first thing to say, because everything else in the system flows from it. We could not train on real repair requests. So we wrote a year's worth of synthetic ones.&lt;/p&gt;

&lt;p&gt;What is real: 70 communities, house counts, crew hubs, road closures, airstrips, and response-time data. All sourced, all genuine geography. The portal keeps that boundary visible. Synthetic requests are labeled as synthetic inside the product. The demo at &lt;a href="https://reachnt.vercel.app" rel="noopener noreferrer"&gt;https://reachnt.vercel.app&lt;/a&gt; does not pretend to be a record of real work.&lt;/p&gt;

&lt;p&gt;This matters more than it sounds. A tool like this only earns trust if it never blurs the line between what happened and what we simulated. So we built the boundary into the product instead of burying it in a README. Anyone clicking through can see which parts are real geography and which parts we made up.&lt;/p&gt;

&lt;h2&gt;
  
  
  3. Ranking repairs without punishing the tenant
&lt;/h2&gt;

&lt;p&gt;The first design decision: queue position must not depend on anything about the tenant. Not when they reported. Not whether they called, emailed, or used an app. Not how much detail they gave. Not their English. Urgency is a property of the fault, not of the person describing it.&lt;/p&gt;

&lt;p&gt;The urgency model reads a tenant's plain-language repair report and scores it. ROC-AUC is 0.84 on wording the model never saw during training. That is a moderate result. It means the model ranks well more often than not, and it still gets things wrong. As part of the whole system, which includes human review of flagged reports, it catches 99.3% of dangerous ones.&lt;/p&gt;

&lt;p&gt;The "as part of the whole system" part carries the weight here. The model on its own is not the safety story. The system around it is. Section 4 is about why that distinction forced a product decision I did not expect to make.&lt;/p&gt;

&lt;h2&gt;
  
  
  4. The calibration problem
&lt;/h2&gt;

&lt;p&gt;The model's ranking is decent. Its confidence is not. When the model said it was at least 90% sure, it was right 56% of the time. That is a badly calibrated model, and showing those numbers to tenants would be dishonest.&lt;/p&gt;

&lt;p&gt;So tenants never see a confidence percentage. And 42% of dangerous reports get routed to a human before any decision is made.&lt;/p&gt;

&lt;p&gt;This was one of the hardest calls in the project. A confidence score looks informative. It is the kind of number a dashboard wants to display. But a number that wrong, shown to someone waiting on a repair, does real damage. It either reassures falsely or worries pointlessly. We chose to show tenants something true instead: a plain-English explanation of why their repair waited as long as it did. Explanations, not probabilities.&lt;/p&gt;

&lt;p&gt;There is a broader point here. Calibration is the number nobody benchmarks and everybody should. A model can rank well and still be unfit to show its own certainty. The fix was not a better model. The fix was admitting what the model could not do and designing around it.&lt;/p&gt;

&lt;h2&gt;
  
  
  5. Shared trips with H3
&lt;/h2&gt;

&lt;p&gt;Ranking is half the system. The other half is getting tradespeople out there without burning the budget. I implemented the batching on Uber's H3 grid.&lt;/p&gt;

&lt;p&gt;H3 tiles the Territory into hexagons. Communities that fall into neighbouring cells get grouped onto shared weekly trips, so one tradesperson covers several in a single run. Across five random synthetic years, shared trips saved $67 to $76 per repair. On a base of roughly $821 per repair, that is a real cut.&lt;/p&gt;

&lt;p&gt;The batching has to talk to the urgency ranking. A shared trip is only useful if the urgent jobs on it still get done first. The planner schedules within each trip by need, so grouping communities never means an urgent repair waits behind a cosmetic one. Batching saves money. Ranking decides order. Neither overrides the other.&lt;/p&gt;

&lt;p&gt;This was my part of the build, and the part I enjoyed most. Hexagons are a clean abstraction for a messy problem. Remote communities are not laid out on a grid, roads flood, and airstrips matter, and the geometry still has to produce trips a real crew could drive.&lt;/p&gt;

&lt;h2&gt;
  
  
  6. The weekly planner
&lt;/h2&gt;

&lt;p&gt;Weekly plans come from a CP-SAT solver. It proved 99.5% of 26,018 weekly plans optimal, with a median solve time of 8 milliseconds.&lt;/p&gt;

&lt;p&gt;Speed matters here because the plan is a draft until a person signs it. Every weekly plan gets a named coordinator's sign-off before it goes out. The solver optimises cost and fault-days, but it refuses to trade away urgency order. A cheaper plan that bumps an urgent repair behind a routine one is not a valid plan. And the signature is the point. When a tenant asks why their repair waited, there is a person who approved the plan. Not a black box.&lt;/p&gt;

&lt;p&gt;That signature also keeps the human in the loop where it belongs. The solver is fast and near-optimal, but it plans from synthetic requests and scheduled distances. A coordinator who knows the roads and the communities reads the plan before it ships.&lt;/p&gt;

&lt;h2&gt;
  
  
  7. What the numbers say, and what I'd do with real data
&lt;/h2&gt;

&lt;p&gt;Over one synthetic year: ReachNT averaged $821 per repair, with 9 in 10 urgent remote repairs fixed within 3 days, and 61,700 weighted fault-days. The cheapest-first baseline averaged $561 per repair, but urgent remote repairs waited 62 days against 3 days in town, with 233,100 fault-days.&lt;/p&gt;

&lt;p&gt;Cheapest-first looks cheaper per job and produces a system where remote families wait two months for urgent repairs while town waits three days. ReachNT costs more per repair and closes the gap. The tool prices the equity trade-off openly instead of hiding it in an average. That is the whole argument in one paragraph: cost per repair is the wrong thing to optimise if it buys a two-tier system.&lt;/p&gt;

&lt;p&gt;Now the honest part. This is a synthetic evaluation. The repair requests are made up, the tenant behaviour is made up, and a model trained on synthetic text has unknown behaviour on real reports. Three things I would do first with real work orders. Retrain the urgency model on genuine tenant wording, because synthetic phrasing flatters the model. Re-run the calibration analysis, because real confidence curves will differ from synthetic ones. And test the shared-trip batching against actual travel patterns instead of scheduled distances, because flooded roads and seasonal access change everything. We are proposing a pilot in the Katherine hub's 16 communities. That is the setting where these numbers get tested for real.&lt;/p&gt;

&lt;h2&gt;
  
  
  8. The audit that caught a real bug
&lt;/h2&gt;

&lt;p&gt;Before launch, we ran a multi-agent AI audit over the system. It found a genuine bug: a dangerous life-support repair could be downgraded from a photo alone.&lt;/p&gt;

&lt;p&gt;Think about what that means. A tenant uploads a photo, someone reassesses the report from the image, and a repair that keeps medical equipment running gets reclassified as routine. In a system whose entire premise is that urgency decides order, that is the worst failure mode available.&lt;/p&gt;

&lt;p&gt;The fix went into three places. The portal now prevents that downgrade path in the UI. The server validates it. The database design records the original severity so a later edit cannot quietly erase it. One bug, three layers, because a safety property that lives in only one layer is a suggestion.&lt;/p&gt;

&lt;p&gt;That audit is the part of the project I am most glad we did. Everything else in ReachNT is a trade-off we chose on purpose. This was a trade-off we had not chosen, and the audit caught it before a tenant ever could. If you take one practice away from this post, make it that one: get an adversarial review of your safety-critical paths before launch, not after.&lt;/p&gt;




&lt;p&gt;Try the demo: &lt;a href="https://reachnt.vercel.app" rel="noopener noreferrer"&gt;https://reachnt.vercel.app&lt;/a&gt;&lt;br&gt;
Code: &lt;a href="https://github.com/harshrastogii/reachnt" rel="noopener noreferrer"&gt;https://github.com/harshrastogii/reachnt&lt;/a&gt;&lt;/p&gt;

</description>
      <category>ai</category>
      <category>datascience</category>
      <category>opensource</category>
      <category>australia</category>
    </item>
  </channel>
</rss>
