<?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: Samina Parveen</title>
    <description>The latest articles on DEV Community by Samina Parveen (@samina_parveen_11a71af857).</description>
    <link>https://dev.to/samina_parveen_11a71af857</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%2F1625613%2Facda75c0-c00a-4ce7-83e5-4d311f8eab08.jpeg</url>
      <title>DEV Community: Samina Parveen</title>
      <link>https://dev.to/samina_parveen_11a71af857</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/samina_parveen_11a71af857"/>
    <language>en</language>
    <item>
      <title>Your company's docs are lying to you. A graph can tell you which ones.</title>
      <dc:creator>Samina Parveen</dc:creator>
      <pubDate>Sun, 18 Oct 2026 17:54:47 +0000</pubDate>
      <link>https://dev.to/samina_parveen_11a71af857/your-companys-docs-are-lying-to-you-a-graph-can-tell-you-which-ones-dj0</link>
      <guid>https://dev.to/samina_parveen_11a71af857/your-companys-docs-are-lying-to-you-a-graph-can-tell-you-which-ones-dj0</guid>
      <description>&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fy97seij23q2t0qfzvwcd.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fy97seij23q2t0qfzvwcd.png" alt=" " width="800" height="500"&gt;&lt;/a&gt;# Your company's docs are lying to you. A graph can tell you which ones.&lt;/p&gt;

&lt;p&gt;At most companies, "why do we use Kafka?" has an answer. It's in ADR-007, written two years ago by someone who has since left. And the onboarding guide, the ledger runbook and the event-schema doc were all written assuming Kafka. If the team switches to Redpanda next week, all three are wrong the moment the decision is made, and nothing tells you so.&lt;/p&gt;

&lt;p&gt;We built &lt;strong&gt;WhyBase&lt;/strong&gt; for Graph Hacks (WeMakeDevs × FalkorDB, Track 03: Company Brain) to fix that second problem. Search tools already help with the first one. WhyBase knows &lt;em&gt;why&lt;/em&gt; a decision was made, and it knows when a doc has gone out of date.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Live demo: &lt;a href="https://whybase.onrender.com" rel="noopener noreferrer"&gt;https://whybase.onrender.com&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Code: &lt;a href="https://github.com/saminadamn/whybase" rel="noopener noreferrer"&gt;https://github.com/saminadamn/whybase&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F5fyaqy09mpclzbnlt3x9.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F5fyaqy09mpclzbnlt3x9.png" alt=" " width="800" height="500"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Search can find the doc. It can't tell you the doc is wrong.
&lt;/h2&gt;

&lt;p&gt;The obvious way to build a "company brain" is to embed every document and do retrieval. That finds the doc that &lt;em&gt;mentions&lt;/em&gt; Kafka, but "this doc is now wrong" isn't a property of the text. It depends on facts outside the doc:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;the doc assumed decision D-002 ("use Kafka for the event bus"),&lt;/li&gt;
&lt;li&gt;D-002 was superseded yesterday by D-022 ("move to Redpanda"),&lt;/li&gt;
&lt;li&gt;the doc's author left in July,&lt;/li&gt;
&lt;li&gt;two people on the same team still write about that system.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Those are relationships, so we stored them as a graph.&lt;/p&gt;

&lt;h2&gt;
  
  
  The model
&lt;/h2&gt;

&lt;p&gt;Six node labels and twelve relationship types:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Person -MEMBER_OF-&amp;gt; Team -OWNS-&amp;gt; System
Project -USES-&amp;gt; System
Project -RELIES_ON-&amp;gt; Decision
Decision -RELIES_ON-&amp;gt; Decision
Decision -SUPERSEDES-&amp;gt; Decision
Decision -ABOUT-&amp;gt; System
Decision -RECORDED_IN-&amp;gt; Source
Decision -MADE_BY-&amp;gt; Person
Source -AUTHORED_BY-&amp;gt; Person
Source -MENTIONS-&amp;gt; System
Source -ASSUMES-&amp;gt; Decision
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;ASSUMES&lt;/code&gt; does the most work. It means "this doc is only true while that decision holds." A doc that &lt;code&gt;ASSUMES&lt;/code&gt; a superseded decision is stale by definition, with no NLP involved.&lt;/p&gt;

&lt;p&gt;Our demo company is Kettle Labs, which is fictional: 23 people, 6 teams, 13 systems, 10 projects, 47 sources and 21 decisions, all synthetic. We wrote the data so the interesting cases show up: superseded decision chains, people who left, and a system nobody has written about.&lt;/p&gt;

&lt;h2&gt;
  
  
  Every question is a traversal
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;"Why do we use Kafka?"&lt;/strong&gt; Start at the system, find the active decision about it, then walk the supersede chain backwards with its sources and deciders:&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="nc"&gt;:System&lt;/span&gt; &lt;span class="ss"&gt;{&lt;/span&gt;&lt;span class="py"&gt;name:&lt;/span&gt;&lt;span class="n"&gt;$system&lt;/span&gt;&lt;span class="ss"&gt;})&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;-&lt;/span&gt;&lt;span class="ss"&gt;[&lt;/span&gt;&lt;span class="nc"&gt;:ABOUT&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;d:&lt;/span&gt;&lt;span class="n"&gt;Decision&lt;/span&gt; &lt;span class="ss"&gt;{&lt;/span&gt;&lt;span class="py"&gt;status:&lt;/span&gt;&lt;span class="s1"&gt;'active'&lt;/span&gt;&lt;span class="ss"&gt;})&lt;/span&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="n"&gt;d&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;:SUPERSEDES&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="o"&gt;..&lt;/span&gt;&lt;span class="m"&gt;5&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;old:&lt;/span&gt;&lt;span class="n"&gt;Decision&lt;/span&gt;&lt;span class="ss"&gt;)&lt;/span&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="n"&gt;old&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;:RECORDED_IN&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;src:&lt;/span&gt;&lt;span class="n"&gt;Source&lt;/span&gt;&lt;span class="ss"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;OPTIONAL&lt;/span&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="n"&gt;old&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;:MADE_BY&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;who:&lt;/span&gt;&lt;span class="n"&gt;Person&lt;/span&gt;&lt;span class="ss"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;RETURN&lt;/span&gt; &lt;span class="n"&gt;d.id&lt;/span&gt; &lt;span class="k"&gt;AS&lt;/span&gt; &lt;span class="n"&gt;head&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;step&lt;/span&gt;&lt;span class="ss"&gt;,&lt;/span&gt; &lt;span class="n"&gt;old.id&lt;/span&gt; &lt;span class="k"&gt;AS&lt;/span&gt; &lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="ss"&gt;,&lt;/span&gt; &lt;span class="n"&gt;old.summary&lt;/span&gt; &lt;span class="k"&gt;AS&lt;/span&gt; &lt;span class="n"&gt;decision&lt;/span&gt;&lt;span class="ss"&gt;,&lt;/span&gt;
       &lt;span class="n"&gt;src.title&lt;/span&gt; &lt;span class="k"&gt;AS&lt;/span&gt; &lt;span class="n"&gt;source&lt;/span&gt;&lt;span class="ss"&gt;,&lt;/span&gt; &lt;span class="n"&gt;who.name&lt;/span&gt; &lt;span class="k"&gt;AS&lt;/span&gt; &lt;span class="k"&gt;by&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;head&lt;/span&gt;&lt;span class="ss"&gt;,&lt;/span&gt; &lt;span class="n"&gt;step&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The answer comes back as a path, &lt;code&gt;event-bus ← D-002 → SUPERSEDES → D-001&lt;/code&gt;, with ADR-007 and ADR-001 attached. The UI draws that path on the graph, so you can check the answer yourself.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;"Which docs are now wrong, and who should fix them?"&lt;/strong&gt; This one query is why we used a graph:&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;src:&lt;/span&gt;&lt;span class="n"&gt;Source&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;:ASSUMES&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;old:&lt;/span&gt;&lt;span class="n"&gt;Decision&lt;/span&gt; &lt;span class="ss"&gt;{&lt;/span&gt;&lt;span class="py"&gt;status:&lt;/span&gt;&lt;span class="s1"&gt;'superseded'&lt;/span&gt;&lt;span class="ss"&gt;})&lt;/span&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="n"&gt;old&lt;/span&gt;&lt;span class="ss"&gt;)&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;-&lt;/span&gt;&lt;span class="ss"&gt;[&lt;/span&gt;&lt;span class="nc"&gt;:SUPERSEDES&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;5&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;head:&lt;/span&gt;&lt;span class="n"&gt;Decision&lt;/span&gt; &lt;span class="ss"&gt;{&lt;/span&gt;&lt;span class="py"&gt;status:&lt;/span&gt;&lt;span class="s1"&gt;'active'&lt;/span&gt;&lt;span class="ss"&gt;})&lt;/span&gt;
&lt;span class="k"&gt;OPTIONAL&lt;/span&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="n"&gt;src&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;:AUTHORED_BY&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;author:&lt;/span&gt;&lt;span class="n"&gt;Person&lt;/span&gt;&lt;span class="ss"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;OPTIONAL&lt;/span&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="n"&gt;author&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;:MEMBER_OF&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="nc"&gt;:Team&lt;/span&gt;&lt;span class="ss"&gt;)&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;-&lt;/span&gt;&lt;span class="ss"&gt;[&lt;/span&gt;&lt;span class="nc"&gt;:MEMBER_OF&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;mate:&lt;/span&gt;&lt;span class="n"&gt;Person&lt;/span&gt; &lt;span class="ss"&gt;{&lt;/span&gt;&lt;span class="py"&gt;status:&lt;/span&gt;&lt;span class="s1"&gt;'active'&lt;/span&gt;&lt;span class="ss"&gt;})&lt;/span&gt;
&lt;span class="n"&gt;...&lt;/span&gt;
&lt;span class="k"&gt;RETURN&lt;/span&gt; &lt;span class="n"&gt;src.title&lt;/span&gt; &lt;span class="k"&gt;AS&lt;/span&gt; &lt;span class="n"&gt;stale_doc&lt;/span&gt;&lt;span class="ss"&gt;,&lt;/span&gt; &lt;span class="n"&gt;head.summary&lt;/span&gt; &lt;span class="k"&gt;AS&lt;/span&gt; &lt;span class="n"&gt;now_true&lt;/span&gt;&lt;span class="ss"&gt;,&lt;/span&gt;
       &lt;span class="k"&gt;CASE&lt;/span&gt; &lt;span class="k"&gt;WHEN&lt;/span&gt; &lt;span class="n"&gt;author.status&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'active'&lt;/span&gt; &lt;span class="k"&gt;THEN&lt;/span&gt; &lt;span class="ss"&gt;[&lt;/span&gt;&lt;span class="n"&gt;author.name&lt;/span&gt;&lt;span class="ss"&gt;]&lt;/span&gt; &lt;span class="k"&gt;ELSE&lt;/span&gt; &lt;span class="n"&gt;mates&lt;/span&gt;&lt;span class="ss"&gt;[&lt;/span&gt;&lt;span class="n"&gt;..2&lt;/span&gt;&lt;span class="ss"&gt;]&lt;/span&gt; &lt;span class="k"&gt;END&lt;/span&gt; &lt;span class="k"&gt;AS&lt;/span&gt; &lt;span class="n"&gt;fix_by&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If the author is still around, they get the fix. If they've left, it goes to active teammates, ranked by how many docs they've written about the same systems.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;"What breaks if we reverse D-002?"&lt;/strong&gt; is a variable-length walk over &lt;code&gt;RELIES_ON&lt;/code&gt;, up to three hops, across decisions and projects:&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="n"&gt;x&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;:RELIES_ON&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;3&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="nc"&gt;:Decision&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;$id&lt;/span&gt;&lt;span class="ss"&gt;})&lt;/span&gt;
&lt;span class="k"&gt;RETURN&lt;/span&gt; &lt;span class="k"&gt;DISTINCT&lt;/span&gt; &lt;span class="nf"&gt;coalesce&lt;/span&gt;&lt;span class="ss"&gt;(&lt;/span&gt;&lt;span class="n"&gt;x.name&lt;/span&gt;&lt;span class="ss"&gt;,&lt;/span&gt; &lt;span class="n"&gt;x.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;affected&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;On our data, reversing D-002 hits 7 things, including the Instant Refunds project, three hops away.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;"Which decisions are load-bearing?"&lt;/strong&gt; FalkorDB has PageRank built in, so this took one line:&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;CALL&lt;/span&gt; &lt;span class="n"&gt;algo.pageRank&lt;/span&gt;&lt;span class="ss"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'Decision'&lt;/span&gt;&lt;span class="ss"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'RELIES_ON'&lt;/span&gt;&lt;span class="ss"&gt;)&lt;/span&gt; &lt;span class="k"&gt;YIELD&lt;/span&gt; &lt;span class="n"&gt;node&lt;/span&gt;&lt;span class="ss"&gt;,&lt;/span&gt; &lt;span class="n"&gt;score&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;D-002 ranks first. That's useful to know before anyone reverses it.&lt;/p&gt;

&lt;p&gt;We also answer &lt;strong&gt;"what did we believe about event-bus on 2025-01-01?"&lt;/strong&gt; by filtering decisions on &lt;code&gt;at &amp;lt;= date &amp;lt; superseded_at&lt;/code&gt; (it was RabbitMQ). &lt;strong&gt;"Which systems does only one active person still know?"&lt;/strong&gt; comes from counting authors per system, split by active and left. payments-ledger shows up: Arjun wrote five docs about it and left, and Rohan is the only active person who knows it.&lt;/p&gt;

&lt;h2&gt;
  
  
  The demo moment: a decision changes
&lt;/h2&gt;

&lt;p&gt;You paste a message into the app:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Team call today: we're moving event-bus from Kafka to Redpanda. Kafka ops cost is too high and Redpanda speaks the Kafka API. — Priya Nair&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;WhyBase reads it and &lt;em&gt;proposes&lt;/em&gt; a write: system &lt;code&gt;event-bus&lt;/code&gt;, replaces D-002, decided by Priya Nair. Nothing is written until you click &lt;strong&gt;Confirm &amp;amp; record&lt;/strong&gt;. Then it creates D-022 with a &lt;code&gt;SUPERSEDES&lt;/code&gt; edge to D-002, and the stale-docs counter jumps from 3 to 6. Three docs flash orange. The ledger guide's author has left, so its fix goes to Rohan Das and Ishaan Kapoor.&lt;/p&gt;

&lt;p&gt;Ask "Why do we use Kafka?" again and you no longer get a plain answer. It comes back marked &lt;strong&gt;out of date&lt;/strong&gt;, pointing to D-022.&lt;/p&gt;

&lt;h2&gt;
  
  
  Keeping the AI honest
&lt;/h2&gt;

&lt;p&gt;An LLM that writes its own Cypher against your company graph is a bad idea, so ours doesn't.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;The model only picks tools.&lt;/strong&gt; There are seven (&lt;code&gt;why&lt;/code&gt;, &lt;code&gt;stale_docs&lt;/code&gt;, &lt;code&gt;who_knows&lt;/code&gt;, &lt;code&gt;knowledge_risk&lt;/code&gt;, &lt;code&gt;reversal_impact&lt;/code&gt;, &lt;code&gt;load_bearing&lt;/code&gt;, &lt;code&gt;as_of&lt;/code&gt;), and each maps to one hand-written &lt;code&gt;.cypher&lt;/code&gt; file. The model fills in arguments and never sees a query string. There are 30 query files in total, all in &lt;code&gt;backend/queries/&lt;/code&gt;, all parameterised.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Names are resolved first.&lt;/strong&gt; Every system, person or decision the model mentions is looked up in the graph before any traversal runs. Ask "Who knows quantum-cache?" and the answer is "unknown", with only the resolver in the trace.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Reads can't write.&lt;/strong&gt; Every agent read goes through &lt;code&gt;graph.ro_query&lt;/code&gt;. Only the confirmed ingest step uses &lt;code&gt;graph.query&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The answer gets checked.&lt;/strong&gt; Every name or ID in the model's sentence has to appear in the rows the query returned. If one doesn't, we throw the sentence away and use a template built from the rows. The footer says which name failed.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The app also runs with no LLM at all. A keyword router picks the tool and the answers are template sentences. That turned out to matter, because the Gemini free tier we tested on allows only 20 requests a day for some models. We defaulted to &lt;code&gt;gemini-3.1-flash-lite&lt;/code&gt;, and when the quota runs out the header says so and answers come from the offline router.&lt;/p&gt;

&lt;h2&gt;
  
  
  Things that bit us
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;The client connects in its constructor.&lt;/strong&gt; &lt;code&gt;FalkorDB(host=...)&lt;/code&gt; runs &lt;code&gt;INFO&lt;/code&gt; straight away to check for Sentinel. On our first Render deploy the host was wrong, and the app died on startup with a raw redis &lt;code&gt;ConnectionError&lt;/code&gt; instead of showing our "Graph down" banner. The fix was to treat building the client like any other query that can fail.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;"localhost" means something different in the cloud.&lt;/strong&gt; Our second deploy failed the same way, because the Render environment had &lt;code&gt;FALKOR_HOST=localhost&lt;/code&gt;. On Render that's the app's own container, and no database was running there.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;So we put the database in the container.&lt;/strong&gt; The final image copies &lt;code&gt;redis-server&lt;/code&gt; and &lt;code&gt;falkordb.so&lt;/code&gt; from the official FalkorDB image (pinned by digest) into our Python image. A small start script launches it when no external host is set. The whole thing runs in under 190 MB on Render's free 512 MB tier. The graph is in-memory and the app reloads Kettle Labs on every start. That's fine for a demo, and the same image still talks to an external FalkorDB when you set &lt;code&gt;FALKOR_HOST&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Smaller ones.&lt;/strong&gt; Reading from a graph that doesn't exist yet raises an "empty key" error instead of returning no rows, so our auto-seed had to handle that. The Docker image's default 1-second query timeout occasionally tripped on reads, so read queries retry once.&lt;/p&gt;

&lt;h2&gt;
  
  
  What we'd build next
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Ingest from Slack and GitHub directly, instead of pasting messages&lt;/li&gt;
&lt;li&gt;Infer &lt;code&gt;ASSUMES&lt;/code&gt; edges when a doc is written, instead of hand-labelling them in the seed data&lt;/li&gt;
&lt;li&gt;Send "your doc is out of date" notifications to the people &lt;code&gt;fix_by&lt;/code&gt; names&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Try it
&lt;/h2&gt;

&lt;p&gt;Open &lt;a href="https://whybase.onrender.com" rel="noopener noreferrer"&gt;https://whybase.onrender.com&lt;/a&gt;. It's a free instance, so the first load can take up to 50 seconds. Use the &lt;strong&gt;Examples&lt;/strong&gt; button for ready-made questions, and &lt;strong&gt;Reset demo&lt;/strong&gt; puts the graph back. Every query the product uses is listed in the README, and &lt;code&gt;docker compose up&lt;/code&gt; runs it locally.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Built by Samina Parveen, Madhur Tandon and Aditya Karn. We wrote the spec, and Claude Code generated most of the code from it; details are in AI_DISCLOSURE.md. All data is synthetic.&lt;/em&gt;&lt;/p&gt;

</description>
    </item>
    <item>
      <title>[Boost]</title>
      <dc:creator>Samina Parveen</dc:creator>
      <pubDate>Fri, 25 Jul 2025 13:19:21 +0000</pubDate>
      <link>https://dev.to/samina_parveen_11a71af857/-2do8</link>
      <guid>https://dev.to/samina_parveen_11a71af857/-2do8</guid>
      <description>&lt;div class="ltag__link--embedded"&gt;
  &lt;div class="crayons-story "&gt;
  &lt;a href="https://dev.to/kaushal_thota_d1b39ace995/hustl-the-student-powered-task-app-born-from-failing-an-exam-2heb" class="crayons-story__hidden-navigation-link"&gt;Hustl: The Student-Powered Task App Born From Failing An Exam.&lt;/a&gt;


  &lt;div class="crayons-story__body crayons-story__body-full_post"&gt;
      &lt;a href="https://dev.to/kaushal_thota_d1b39ace995/hustl-the-student-powered-task-app-born-from-failing-an-exam-2heb" class="crayons-article__context-note crayons-article__context-note__feed"&gt;&lt;p&gt;WLH Challenge: Beyond the Code Submission&lt;/p&gt;

&lt;/a&gt;
    &lt;div class="crayons-story__top"&gt;
      &lt;div class="crayons-story__meta"&gt;
        &lt;div class="crayons-story__author-pic"&gt;

          &lt;a href="/kaushal_thota_d1b39ace995" class="crayons-avatar  crayons-avatar--l  "&gt;
            &lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3370844%2Fee7cb915-23e7-4f3b-a2c7-83ac698174ec.png" alt="kaushal_thota_d1b39ace995 profile" class="crayons-avatar__image"&gt;
          &lt;/a&gt;
        &lt;/div&gt;
        &lt;div&gt;
          &lt;div&gt;
            &lt;a href="/kaushal_thota_d1b39ace995" class="crayons-story__secondary fw-medium m:hidden"&gt;
              Kaushal Thota
            &lt;/a&gt;
            &lt;div class="profile-preview-card relative mb-4 s:mb-0 fw-medium hidden m:inline-block"&gt;
              
                Kaushal Thota
                
              
              &lt;div id="story-author-preview-content-2717537" class="profile-preview-card__content crayons-dropdown branded-7 p-4 pt-0"&gt;
                &lt;div class="gap-4 grid"&gt;
                  &lt;div class="-mt-4"&gt;
                    &lt;a href="/kaushal_thota_d1b39ace995" class="flex"&gt;
                      &lt;span class="crayons-avatar crayons-avatar--xl mr-2 shrink-0"&gt;
                        &lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3370844%2Fee7cb915-23e7-4f3b-a2c7-83ac698174ec.png" class="crayons-avatar__image" alt=""&gt;
                      &lt;/span&gt;
                      &lt;span class="crayons-link crayons-subtitle-2 mt-5"&gt;Kaushal Thota&lt;/span&gt;
                    &lt;/a&gt;
                  &lt;/div&gt;
                  &lt;div class="print-hidden"&gt;
                    
                      Follow
                    
                  &lt;/div&gt;
                  &lt;div class="author-preview-metadata-container"&gt;&lt;/div&gt;
                &lt;/div&gt;
              &lt;/div&gt;
            &lt;/div&gt;

          &lt;/div&gt;
          &lt;a href="https://dev.to/kaushal_thota_d1b39ace995/hustl-the-student-powered-task-app-born-from-failing-an-exam-2heb" class="crayons-story__tertiary fs-xs"&gt;&lt;time&gt;Jul 23 '25&lt;/time&gt;&lt;span class="time-ago-indicator-initial-placeholder"&gt;&lt;/span&gt;&lt;/a&gt;
        &lt;/div&gt;
      &lt;/div&gt;

    &lt;/div&gt;

    &lt;div class="crayons-story__indention"&gt;
      &lt;h2 class="crayons-story__title crayons-story__title-full_post"&gt;
        &lt;a href="https://dev.to/kaushal_thota_d1b39ace995/hustl-the-student-powered-task-app-born-from-failing-an-exam-2heb" id="article-link-2717537"&gt;
          Hustl: The Student-Powered Task App Born From Failing An Exam.
        &lt;/a&gt;
      &lt;/h2&gt;
        &lt;div class="crayons-story__tags"&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/devchallenge"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;devchallenge&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/wlhchallenge"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;wlhchallenge&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/community"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;community&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/networking"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;networking&lt;/a&gt;
        &lt;/div&gt;
      &lt;div class="crayons-story__bottom"&gt;
        &lt;div class="crayons-story__details"&gt;
          &lt;a href="https://dev.to/kaushal_thota_d1b39ace995/hustl-the-student-powered-task-app-born-from-failing-an-exam-2heb" class="crayons-btn crayons-btn--s crayons-btn--ghost crayons-btn--icon-left"&gt;
            &lt;div class="multiple_reactions_aggregate"&gt;
              &lt;span class="multiple_reactions_icons_container"&gt;
                  &lt;span class="crayons_icon_container"&gt;
                    &lt;img src="https://assets.dev.to/assets/fire-f60e7a582391810302117f987b22a8ef04a2fe0df7e3258a5f49332df1cec71e.svg" width="18" height="18"&gt;
                  &lt;/span&gt;
                  &lt;span class="crayons_icon_container"&gt;
                    &lt;img src="https://assets.dev.to/assets/raised-hands-74b2099fd66a39f2d7eed9305ee0f4553df0eb7b4f11b01b6b1b499973048fe5.svg" width="18" height="18"&gt;
                  &lt;/span&gt;
                  &lt;span class="crayons_icon_container"&gt;
                    &lt;img src="https://assets.dev.to/assets/sparkle-heart-5f9bee3767e18deb1bb725290cb151c25234768a0e9a2bd39370c382d02920cf.svg" width="18" height="18"&gt;
                  &lt;/span&gt;
              &lt;/span&gt;
              &lt;span class="aggregate_reactions_counter"&gt;19&lt;span class="hidden s:inline"&gt;&amp;nbsp;reactions&lt;/span&gt;&lt;/span&gt;
            &lt;/div&gt;
          &lt;/a&gt;
            &lt;a href="https://dev.to/kaushal_thota_d1b39ace995/hustl-the-student-powered-task-app-born-from-failing-an-exam-2heb#comments" class="crayons-btn crayons-btn--s crayons-btn--ghost crayons-btn--icon-left flex items-center"&gt;
              

              3&lt;span class="hidden s:inline"&gt;&amp;nbsp;comments&lt;/span&gt;
            &lt;/a&gt;
        &lt;/div&gt;
        &lt;div class="crayons-story__save"&gt;
          &lt;small class="crayons-story__tertiary fs-xs mr-2"&gt;
            5 min read
          &lt;/small&gt;
            
              &lt;span class="bm-initial"&gt;
                

              &lt;/span&gt;
              &lt;span class="bm-success"&gt;
                

              &lt;/span&gt;
            
        &lt;/div&gt;
      &lt;/div&gt;
    &lt;/div&gt;
  &lt;/div&gt;
&lt;/div&gt;

&lt;/div&gt;


</description>
      <category>devchallenge</category>
      <category>wlhchallenge</category>
      <category>community</category>
      <category>networking</category>
    </item>
  </channel>
</rss>
