<?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: Amit Kumar Gupta </title>
    <description>The latest articles on DEV Community by Amit Kumar Gupta  (@amit_intj).</description>
    <link>https://dev.to/amit_intj</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%2F1277719%2F69b24ea3-dc33-4511-b15c-378af8dd9fea.png</url>
      <title>DEV Community: Amit Kumar Gupta </title>
      <link>https://dev.to/amit_intj</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/amit_intj"/>
    <language>en</language>
    <item>
      <title>Slack is a property of the hand-off, not the flight</title>
      <dc:creator>Amit Kumar Gupta </dc:creator>
      <pubDate>Sun, 18 Oct 2026 16:01:56 +0000</pubDate>
      <link>https://dev.to/amit_intj/slack-is-a-property-of-the-hand-off-not-the-flight-41e0</link>
      <guid>https://dev.to/amit_intj/slack-is-a-property-of-the-hand-off-not-the-flight-41e0</guid>
      <description>&lt;p&gt;&lt;em&gt;Building a cascade-containment agent where the graph decides and the model only talks.&lt;/em&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  The thing that kept bothering me
&lt;/h2&gt;

&lt;p&gt;When a flight is delayed, the obvious mental model is that &lt;em&gt;the flight&lt;/em&gt; has a problem. Weather at the airport, a technical issue, a late passenger.&lt;/p&gt;

&lt;p&gt;But that's mostly not where delay comes from. Eurocontrol's CODA Digest measured that &lt;strong&gt;44.6% of European delay minutes in Q2 2023 were knock-on&lt;/strong&gt; — reactionary delay, not primary. In the US, the DOT's Air Travel Consumer Report for September 2025 lists &lt;em&gt;late-arriving aircraft&lt;/em&gt; as the single largest cause.&lt;/p&gt;

&lt;p&gt;Knock-on delay isn't a new problem happening. It's an old problem arriving.&lt;/p&gt;

&lt;p&gt;The reason is structural: an airline flies the same aircraft on four to six legs a day, and the same crew across a subset of those legs. Flight two is waiting on flight one. The dependency is real, it's physical, and it's a graph.&lt;/p&gt;

&lt;p&gt;What made this click for me was the Indian regulator's language after IndiGo's December 2025 collapse — 2,507 cancellations, 1,852 delays, more than three lakh passengers stranded over three days, a ₹22.2 crore penalty. The PIB's finding was that the rosters had &lt;strong&gt;"maximised crew utilisation"&lt;/strong&gt;, cutting roster buffers and increasing reliance on dead-heading, tail swaps and minimal recovery time.&lt;/p&gt;

&lt;p&gt;Maximised utilisation means minimised slack. The schedule was efficient right up until it wasn't.&lt;/p&gt;




&lt;h2&gt;
  
  
  The modelling decision that made everything else easy
&lt;/h2&gt;

&lt;p&gt;My first instinct was to put a &lt;code&gt;slack&lt;/code&gt; property on each flight. That's wrong, and seeing why is the whole project.&lt;/p&gt;

&lt;p&gt;Slack doesn't belong to a flight. It belongs to the &lt;strong&gt;gap between two flights&lt;/strong&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;slack_min = scheduled_ground_time − minimum_legal_turnaround
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A flight isn't fragile. A &lt;em&gt;hand-off&lt;/em&gt; is fragile. So the model has two edge types doing all the work:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Edge&lt;/th&gt;
&lt;th&gt;Meaning&lt;/th&gt;
&lt;th&gt;Properties&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;NEXT_LEG&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;same aircraft, immediately following leg&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;min_turn&lt;/code&gt;, &lt;code&gt;sched_ground&lt;/code&gt;, &lt;code&gt;slack_min&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;CREW_NEXT&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;same crew, immediately following leg&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;min_rest&lt;/code&gt;, &lt;code&gt;sched_ground&lt;/code&gt;, &lt;code&gt;slack_min&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Once slack lives on the edge, cascade propagation becomes something you can write down in one query. Delay spills from flight &lt;code&gt;a&lt;/code&gt; to flight &lt;code&gt;b&lt;/code&gt; exactly when it exceeds the buffer between them:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight cypher"&gt;&lt;code&gt;&lt;span class="k"&gt;MATCH&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="ss"&gt;(&lt;/span&gt;&lt;span class="py"&gt;a:&lt;/span&gt;&lt;span class="n"&gt;Flight&lt;/span&gt;&lt;span class="ss"&gt;)&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="ss"&gt;[&lt;/span&gt;&lt;span class="py"&gt;e:&lt;/span&gt;&lt;span class="n"&gt;NEXT_LEG&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;CREW_NEXT&lt;/span&gt;&lt;span class="ss"&gt;]&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="ss"&gt;(&lt;/span&gt;&lt;span class="py"&gt;b:&lt;/span&gt;&lt;span class="n"&gt;Flight&lt;/span&gt;&lt;span class="ss"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;WHERE&lt;/span&gt; &lt;span class="n"&gt;a.status&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'SCHEDULED'&lt;/span&gt; &lt;span class="ow"&gt;AND&lt;/span&gt; &lt;span class="n"&gt;b.status&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'SCHEDULED'&lt;/span&gt;
  &lt;span class="n"&gt;AND&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="ss"&gt;(&lt;/span&gt;&lt;span class="n"&gt;a.delay_min&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;e.slack_min&lt;/span&gt;&lt;span class="ss"&gt;)&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;b.delay_min&lt;/span&gt;
&lt;span class="k"&gt;WITH&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="ss"&gt;,&lt;/span&gt; &lt;span class="nf"&gt;max&lt;/span&gt;&lt;span class="ss"&gt;(&lt;/span&gt;&lt;span class="n"&gt;a.delay_min&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;e.slack_min&lt;/span&gt;&lt;span class="ss"&gt;)&lt;/span&gt; &lt;span class="k"&gt;AS&lt;/span&gt; &lt;span class="n"&gt;new_delay&lt;/span&gt;
&lt;span class="k"&gt;SET&lt;/span&gt; &lt;span class="n"&gt;b.delay_min&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;new_delay&lt;/span&gt;&lt;span class="ss"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;b.proj_dep&lt;/span&gt;  &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;b.sched_dep&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;new_delay&lt;/span&gt;&lt;span class="ss"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;b.proj_arr&lt;/span&gt;  &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;b.sched_arr&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;new_delay&lt;/span&gt;
&lt;span class="k"&gt;RETURN&lt;/span&gt; &lt;span class="nf"&gt;count&lt;/span&gt;&lt;span class="ss"&gt;(&lt;/span&gt;&lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="ss"&gt;)&lt;/span&gt; &lt;span class="k"&gt;AS&lt;/span&gt; &lt;span class="n"&gt;changed&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Run it until it returns &lt;code&gt;changed = 0&lt;/code&gt;. That's Bellman-Ford relaxation to a fixpoint — in the database, not in application code.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;max()&lt;/code&gt; is doing something subtle and necessary. A flight has two inbound dependencies: its aircraft and its crew. It takes the &lt;strong&gt;worse&lt;/strong&gt; of them, because it waits for both. One aggregation, and that rule is expressed exactly once.&lt;/p&gt;




&lt;h2&gt;
  
  
  Why "why is this flight late?" is the real feature
&lt;/h2&gt;

&lt;p&gt;Here's the query I'd show a judge if I only had one:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight cypher"&gt;&lt;code&gt;&lt;span class="k"&gt;MATCH&lt;/span&gt; &lt;span class="n"&gt;p&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="ss"&gt;(&lt;/span&gt;&lt;span class="py"&gt;root:&lt;/span&gt;&lt;span class="n"&gt;Flight&lt;/span&gt; &lt;span class="ss"&gt;{&lt;/span&gt;&lt;span class="py"&gt;id:&lt;/span&gt; &lt;span class="n"&gt;$root_id&lt;/span&gt;&lt;span class="ss"&gt;})&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="ss"&gt;[&lt;/span&gt;&lt;span class="nc"&gt;:NEXT_LEG&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;CREW_NEXT&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="o"&gt;..&lt;/span&gt;&lt;span class="m"&gt;8&lt;/span&gt;&lt;span class="ss"&gt;]&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="ss"&gt;(&lt;/span&gt;&lt;span class="py"&gt;target:&lt;/span&gt;&lt;span class="n"&gt;Flight&lt;/span&gt; &lt;span class="ss"&gt;{&lt;/span&gt;&lt;span class="py"&gt;id:&lt;/span&gt; &lt;span class="n"&gt;$target_id&lt;/span&gt;&lt;span class="ss"&gt;})&lt;/span&gt;
&lt;span class="k"&gt;RETURN&lt;/span&gt; &lt;span class="ss"&gt;[&lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt; &lt;span class="ow"&gt;IN&lt;/span&gt; &lt;span class="nf"&gt;nodes&lt;/span&gt;&lt;span class="ss"&gt;(&lt;/span&gt;&lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="ss"&gt;)&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;n.id&lt;/span&gt;&lt;span class="ss"&gt;]&lt;/span&gt;                &lt;span class="k"&gt;AS&lt;/span&gt; &lt;span class="n"&gt;chain&lt;/span&gt;&lt;span class="ss"&gt;,&lt;/span&gt;
       &lt;span class="ss"&gt;[&lt;/span&gt;&lt;span class="n"&gt;r&lt;/span&gt; &lt;span class="ow"&gt;IN&lt;/span&gt; &lt;span class="nf"&gt;relationships&lt;/span&gt;&lt;span class="ss"&gt;(&lt;/span&gt;&lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="ss"&gt;)&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="nf"&gt;type&lt;/span&gt;&lt;span class="ss"&gt;(&lt;/span&gt;&lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="ss"&gt;)]&lt;/span&gt;     &lt;span class="k"&gt;AS&lt;/span&gt; &lt;span class="n"&gt;hop_types&lt;/span&gt;&lt;span class="ss"&gt;,&lt;/span&gt;
       &lt;span class="ss"&gt;[&lt;/span&gt;&lt;span class="n"&gt;r&lt;/span&gt; &lt;span class="ow"&gt;IN&lt;/span&gt; &lt;span class="nf"&gt;relationships&lt;/span&gt;&lt;span class="ss"&gt;(&lt;/span&gt;&lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="ss"&gt;)&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;r.slack_min&lt;/span&gt;&lt;span class="ss"&gt;]&lt;/span&gt; &lt;span class="k"&gt;AS&lt;/span&gt; &lt;span class="n"&gt;slack_at_each_hop&lt;/span&gt;&lt;span class="ss"&gt;,&lt;/span&gt;
       &lt;span class="nf"&gt;length&lt;/span&gt;&lt;span class="ss"&gt;(&lt;/span&gt;&lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="ss"&gt;)&lt;/span&gt;                             &lt;span class="k"&gt;AS&lt;/span&gt; &lt;span class="n"&gt;hops&lt;/span&gt;
&lt;span class="k"&gt;ORDER&lt;/span&gt; &lt;span class="k"&gt;BY&lt;/span&gt; &lt;span class="n"&gt;hops&lt;/span&gt; &lt;span class="k"&gt;ASC&lt;/span&gt;
&lt;span class="k"&gt;LIMIT&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It answers "why is this flight late?" with a &lt;em&gt;path&lt;/em&gt;: 6E101 was fogbound → handed its aircraft to 6E117 across a turn with 5 minutes of slack → whose crew carried it to 6E131 across 8 minutes of slack.&lt;/p&gt;

&lt;p&gt;No model wrote that sentence. It's a traversal. If the explanation is wrong, the graph is wrong, and I can go look at the graph.&lt;/p&gt;

&lt;p&gt;This is the part I think is genuinely underrated about graph databases in agent systems. Everyone reaches for them as a retrieval layer — fetch some context, stuff it in a prompt. But a traversal result &lt;em&gt;is&lt;/em&gt; an explanation, structurally. You get provenance for free because the answer is literally the path you walked.&lt;/p&gt;




&lt;h2&gt;
  
  
  Proof by zero rows
&lt;/h2&gt;

&lt;p&gt;The agent can propose actions: cancel a pair of flights, swap in a spare aircraft, swap in reserve crew. Before any of them can be committed, four invariants must hold. Each is a query that &lt;strong&gt;must return nothing&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;INV-1&lt;/strong&gt; — no crew's duty window exceeds its limit&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;INV-2&lt;/strong&gt; — no turnaround is shorter than the minimum&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;INV-3&lt;/strong&gt; — tail continuity: an aircraft's arrival airport equals its next departure airport&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;INV-4&lt;/strong&gt; — every flight has a terminal status&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I want to dwell on INV-3, because my first design didn't have it.&lt;/p&gt;

&lt;p&gt;Cancelling a delayed flight is the obvious containment move. It's also, often, catastrophically wrong — because cancelling a single mid-rotation leg leaves the aircraft in the wrong city for the rest of the day. The aircraft can't teleport. So cancellations have to be done in &lt;strong&gt;out-and-back pairs&lt;/strong&gt;, or paired with an explicit ferry.&lt;/p&gt;

&lt;p&gt;I only found this by writing the invariant down and watching plans fail it. That's the argument for expressing safety as absence-of-a-pattern rather than as application logic: &lt;em&gt;absence of a matching path is the proof of safety&lt;/em&gt;, and a query that returns zero rows is much harder to fool yourself about than an &lt;code&gt;if&lt;/code&gt; statement you forgot to write.&lt;/p&gt;




&lt;h2&gt;
  
  
  Forking the world before touching it
&lt;/h2&gt;

&lt;p&gt;Every plan is evaluated on a &lt;code&gt;GRAPH.COPY&lt;/code&gt; fork:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;fork → apply the plan → re-propagate the cascade → check 4 invariants → score → DELETE fork
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;FalkorDB's &lt;code&gt;GRAPH.COPY&lt;/code&gt; clones nodes, relationships, properties, indexes and constraints, while the source stays readable and writable. The fork is deleted in a &lt;code&gt;finally&lt;/code&gt; block — always, including when the work inside throws, which is its own test.&lt;/p&gt;

&lt;p&gt;One bug worth confessing: relaxation is &lt;strong&gt;monotone&lt;/strong&gt;. It only ever raises a delay. So my first version of the evaluation loop forked, applied a cancellation, re-ran relaxation — and every plan scored identically. Of course it did: cancelling a flight can't &lt;em&gt;reduce&lt;/em&gt; a delay that has already propagated downstream. The fork has to reset to the published schedule and re-propagate from the disruption &lt;em&gt;after&lt;/em&gt; the actions are applied. Obvious in hindsight; invisible until the scores came back suspiciously flat.&lt;/p&gt;




&lt;h2&gt;
  
  
  The constraint that shaped the architecture
&lt;/h2&gt;

&lt;p&gt;I gave myself one rule, borrowed from the hackathon's own:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;The graph decides. The model talks. A human confirms.&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Concretely, in the MCP server, there are nine tools. Eight are read-only. The ninth is &lt;code&gt;commit_plan&lt;/code&gt;, and it takes &lt;strong&gt;only a &lt;code&gt;decision_id&lt;/code&gt;&lt;/strong&gt; — never a plan body.&lt;/p&gt;

&lt;p&gt;That signature is the whole safety argument. The model cannot invent an action, because there is no parameter through which an action could arrive. It can only point at something the graph already verified and recorded. The worst a confused model can do is point at the wrong decision, and even that is caught:&lt;/p&gt;

&lt;p&gt;Every &lt;code&gt;Decision&lt;/code&gt; is stamped with the graph revision it was verified against. If the live graph has moved since, commit &lt;strong&gt;refuses&lt;/strong&gt;. A plan proven safe against one state of the world is not proven safe against another.&lt;/p&gt;




&lt;h2&gt;
  
  
  The test I'd keep if I could only keep one
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="nx"&gt;tests&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nx"&gt;graph&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;off&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;test&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ts&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It points the product at a dead database and asserts that &lt;em&gt;every&lt;/em&gt; path fails. No cache, no default, no degraded mode, no in-memory fallback. It also greps the source for forbidden datastore imports.&lt;/p&gt;

&lt;p&gt;If the product still works with the graph removed, the graph was decoration. This test is how I know it isn't.&lt;/p&gt;

&lt;p&gt;It's also what let me add MongoDB for user accounts without weakening the claim. Accounts are the app shell; flights, edges, cascades, plans, decisions and receipts are the product. Dropping the Mongo database changes no number the product reports — and &lt;code&gt;packages/graph&lt;/code&gt; is forbidden from importing &lt;code&gt;mongoose&lt;/code&gt;, enforced by a linter rather than by my good intentions.&lt;/p&gt;




&lt;h2&gt;
  
  
  What I'd tell myself at the start
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Write the oracle first.&lt;/strong&gt; Before I had a database connection, I wrote a plain-TypeScript checker that validated the generated schedule against the same four invariants the Cypher enforces. It caught three real bugs immediately: a negative crew-rest slack (I'd tightened hand-offs to &lt;code&gt;min_turn&lt;/code&gt; when &lt;code&gt;min_rest&lt;/code&gt; is the longer requirement), a rotation overrunning the 23:00 day boundary, and over-eager crew chunking. An independent implementation of the same rule is worth more than another test of the same implementation.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Put every query in one file.&lt;/strong&gt; All the Cypher lives in &lt;code&gt;queries.ts&lt;/code&gt; — none inline in a route, a script or a test. It makes the "here are the queries this depends on" section of the README a copy-paste, and it makes the queries reviewable as a set.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Name your relationships.&lt;/strong&gt; FalkorDB only existence-checks unnamed relationships. &lt;code&gt;MATCH (a)-[e:NEXT_LEG]-&amp;gt;(b)&lt;/code&gt; where you actually use &lt;code&gt;e&lt;/code&gt; behaves correctly; drop the alias and your counts can quietly go wrong.&lt;/p&gt;




&lt;h2&gt;
  
  
  What this is and isn't
&lt;/h2&gt;

&lt;p&gt;It's a decision-support prototype on &lt;strong&gt;synthetic data&lt;/strong&gt;. Every flight, tail, crew member and passenger count is generated; only airport codes and coordinates are real.&lt;/p&gt;

&lt;p&gt;It is explicitly &lt;strong&gt;not&lt;/strong&gt; a replacement for operations solvers. Lufthansa's OPSD is a mature deployed system; INFORMS reported controllers accepted 26% of its suggestions, and around twenty developers spent four years mostly on data preparation. That 26% is a published figure. &lt;em&gt;Why&lt;/em&gt; it's 26% is my hypothesis, not a finding — but it's the hypothesis the project is built around: an operations controller is personally accountable for the decision, and a recommendation you can't interrogate is a recommendation you have to take on faith.&lt;/p&gt;

&lt;p&gt;So the position isn't "better plans". It's: see the whole chain, explain every suggestion as a path, and test it against hard constraints before anyone acts.&lt;/p&gt;

&lt;p&gt;The containment selection is a scored heuristic with declared weights, not a proof of optimality. The invariants only cover what's modelled — bad input data can still produce a plan that passes verification. And &lt;code&gt;duty_limit_min = 780&lt;/code&gt; is a placeholder parameter, not a regulatory figure; reading the actual DGCA FDTL CAR is still on the list.&lt;/p&gt;




</description>
      <category>agents</category>
      <category>ai</category>
      <category>architecture</category>
      <category>llm</category>
    </item>
  </channel>
</rss>
