<?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: Arvind Jolly</title>
    <description>The latest articles on DEV Community by Arvind Jolly (@arvindjolly).</description>
    <link>https://dev.to/arvindjolly</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%2F3990886%2F81a24a23-2096-44a7-bbd3-b129d26223df.png</url>
      <title>DEV Community: Arvind Jolly</title>
      <link>https://dev.to/arvindjolly</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/arvindjolly"/>
    <language>en</language>
    <item>
      <title>How We Modeled Conflicting Historical Knowledge Without Breaking Our Database</title>
      <dc:creator>Arvind Jolly</dc:creator>
      <pubDate>Thu, 18 Jun 2026 12:37:54 +0000</pubDate>
      <link>https://dev.to/arvindjolly/how-we-modeled-conflicting-historical-knowledge-without-breaking-our-database-4okj</link>
      <guid>https://dev.to/arvindjolly/how-we-modeled-conflicting-historical-knowledge-without-breaking-our-database-4okj</guid>
      <description>&lt;h3&gt;
  
  
  How building an AI-powered geomancy platform forced us to rethink data modeling
&lt;/h3&gt;

&lt;p&gt;Most software systems assume that there is a single source of truth.&lt;/p&gt;

&lt;p&gt;A user has one email address.&lt;/p&gt;

&lt;p&gt;A product has one price.&lt;/p&gt;

&lt;p&gt;An order has one status.&lt;/p&gt;

&lt;p&gt;Databases, APIs, and validation layers are typically designed around this assumption.&lt;/p&gt;

&lt;p&gt;But what happens when your domain contains multiple valid truths?&lt;/p&gt;

&lt;p&gt;This was a problem we encountered while building &lt;strong&gt;SAGE&lt;/strong&gt;, an AI-powered geomantic platform that supports multiple historical traditions, including Western Geomancy and Indian Ramal.&lt;/p&gt;

&lt;p&gt;Unexpectedly, the hardest challenge wasn't AI.&lt;/p&gt;

&lt;p&gt;It was data modeling.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Problem
&lt;/h2&gt;

&lt;p&gt;Geomancy is built around sixteen foundational figures.&lt;/p&gt;

&lt;p&gt;Each figure carries various attributes:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Element&lt;/li&gt;
&lt;li&gt;Planetary ruler&lt;/li&gt;
&lt;li&gt;Zodiac association&lt;/li&gt;
&lt;li&gt;Interpretive meanings&lt;/li&gt;
&lt;li&gt;Dignities and conditions&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The complication?&lt;/p&gt;

&lt;p&gt;Different historical traditions don't always agree.&lt;/p&gt;

&lt;p&gt;For example, a figure may have one set of correspondences in a Western lineage and a different set in an Indo-Persian Ramal lineage.&lt;/p&gt;

&lt;p&gt;From a historical perspective, this is normal.&lt;/p&gt;

&lt;p&gt;From a software perspective, it creates an immediate design problem.&lt;/p&gt;

&lt;p&gt;A naïve schema might look like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;CREATE&lt;/span&gt; &lt;span class="k"&gt;TABLE&lt;/span&gt; &lt;span class="n"&gt;figures&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;id&lt;/span&gt; &lt;span class="nb"&gt;VARCHAR&lt;/span&gt; &lt;span class="k"&gt;PRIMARY&lt;/span&gt; &lt;span class="k"&gt;KEY&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;name&lt;/span&gt; &lt;span class="nb"&gt;VARCHAR&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;element&lt;/span&gt; &lt;span class="nb"&gt;VARCHAR&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;planet&lt;/span&gt; &lt;span class="nb"&gt;VARCHAR&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;zodiac&lt;/span&gt; &lt;span class="nb"&gt;VARCHAR&lt;/span&gt;
&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Looks fine.&lt;/p&gt;

&lt;p&gt;Until two legitimate traditions assign different values to the same figure.&lt;/p&gt;

&lt;p&gt;Now the database is asking a question that historians have debated for centuries:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Which version is correct?&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  The Wrong Solution
&lt;/h2&gt;

&lt;p&gt;Many systems solve this by choosing one authority.&lt;/p&gt;

&lt;p&gt;In effect:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;One Figure
↓
One Interpretation
↓
One Truth
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This simplifies implementation.&lt;/p&gt;

&lt;p&gt;It also destroys historical fidelity.&lt;/p&gt;

&lt;p&gt;As soon as we hardcode one interpretation, every other lineage becomes "wrong" according to the software.&lt;/p&gt;

&lt;p&gt;That wasn't acceptable.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Shift: Truth as Context
&lt;/h2&gt;

&lt;p&gt;The breakthrough came when we stopped treating interpretations as facts.&lt;/p&gt;

&lt;p&gt;Instead, we treated them as context.&lt;/p&gt;

&lt;p&gt;The identity of a figure remains constant.&lt;/p&gt;

&lt;p&gt;Its attributes become lineage-dependent.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"figure"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"puer"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"binary_signature"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"1101"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"lineages"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"agrippa_western"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"element"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"fire"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"planet"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"mars"&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"ramal_traditional"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"element"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"air"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"planet"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"mars"&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now the question becomes:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;What is the element of Puer
within this lineage?
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;instead of&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;What is the element of Puer?
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This distinction changed the entire architecture.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Registry Pattern
&lt;/h2&gt;

&lt;p&gt;Duplicating complete datasets for every tradition would quickly become unmaintainable.&lt;/p&gt;

&lt;p&gt;Most lineages agree on the majority of attributes.&lt;/p&gt;

&lt;p&gt;Only a small percentage differ.&lt;/p&gt;

&lt;p&gt;To solve this, we implemented a layered registry pattern.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;FigureRegistry&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;get_attribute&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;figure_id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;attribute&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;lineage&lt;/span&gt;
    &lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="nf"&gt;lineage_override_exists&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;override&lt;/span&gt;

        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;baseline&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Resolution order:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Lineage Override
        ↓
Tradition Baseline
        ↓
Default Registry
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This gave us:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Smaller datasets&lt;/li&gt;
&lt;li&gt;Easier maintenance&lt;/li&gt;
&lt;li&gt;Cleaner onboarding of new traditions&lt;/li&gt;
&lt;li&gt;Reduced duplication&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Most importantly, it allowed the system to grow without rewriting existing data.&lt;/p&gt;




&lt;h2&gt;
  
  
  Why Snapshots Matter
&lt;/h2&gt;

&lt;p&gt;The next challenge was versioning.&lt;/p&gt;

&lt;p&gt;Suppose a reading is generated today.&lt;/p&gt;

&lt;p&gt;Six months later, historical research leads us to revise part of a lineage definition.&lt;/p&gt;

&lt;p&gt;Should old readings change?&lt;/p&gt;

&lt;p&gt;Absolutely not.&lt;/p&gt;

&lt;p&gt;A reading should remain reproducible forever.&lt;/p&gt;

&lt;p&gt;The solution was to store a resolved snapshot with every generated reading.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"reading_id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"rdg_892347"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"tradition"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"western_agrippa"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"schema_version"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"v1.2.0"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"resolved_attributes"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"puer"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"element"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"fire"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"planet"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"mars"&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This gives us:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Auditability&lt;/li&gt;
&lt;li&gt;Reproducibility&lt;/li&gt;
&lt;li&gt;Historical consistency&lt;/li&gt;
&lt;li&gt;Easier debugging&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Every reading becomes self-contained.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Broader Pattern
&lt;/h2&gt;

&lt;p&gt;Although this project involved geomancy, the underlying problem appears everywhere.&lt;/p&gt;

&lt;p&gt;Examples:&lt;/p&gt;

&lt;h3&gt;
  
  
  Legal Systems
&lt;/h3&gt;

&lt;p&gt;Different jurisdictions interpret regulations differently.&lt;/p&gt;

&lt;h3&gt;
  
  
  Medicine
&lt;/h3&gt;

&lt;p&gt;Clinical guidelines change over time.&lt;/p&gt;

&lt;h3&gt;
  
  
  Finance
&lt;/h3&gt;

&lt;p&gt;Accounting standards vary across countries.&lt;/p&gt;

&lt;h3&gt;
  
  
  Taxation
&lt;/h3&gt;

&lt;p&gt;Rules differ by region and version.&lt;/p&gt;

&lt;h3&gt;
  
  
  Historical Archives
&lt;/h3&gt;

&lt;p&gt;Sources often contradict each other.&lt;/p&gt;

&lt;p&gt;The common challenge is this:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Multiple valid interpretations must coexist inside a single system.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Traditional CRUD thinking doesn't solve that elegantly.&lt;/p&gt;

&lt;p&gt;Context-aware architectures do.&lt;/p&gt;




&lt;h2&gt;
  
  
  What We Learned
&lt;/h2&gt;

&lt;p&gt;The most valuable lesson wasn't about AI.&lt;/p&gt;

&lt;p&gt;It was about knowledge representation.&lt;/p&gt;

&lt;p&gt;Many domains don't contain a single source of truth.&lt;/p&gt;

&lt;p&gt;They contain multiple authoritative perspectives.&lt;/p&gt;

&lt;p&gt;The job of software architecture isn't always to eliminate disagreement.&lt;/p&gt;

&lt;p&gt;Sometimes it's to model disagreement cleanly.&lt;/p&gt;

&lt;p&gt;Once we accepted that idea, the architecture became significantly simpler.&lt;/p&gt;

&lt;p&gt;Instead of forcing competing traditions into a single schema, we designed a system that allows multiple traditions to coexist while sharing a common framework.&lt;/p&gt;

&lt;p&gt;In hindsight, that turned out to be a much more scalable solution than trying to determine which historical authority was "correct."&lt;/p&gt;




&lt;h2&gt;
  
  
  Final Thought
&lt;/h2&gt;

&lt;p&gt;If your domain contains:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;competing authorities&lt;/li&gt;
&lt;li&gt;evolving standards&lt;/li&gt;
&lt;li&gt;multiple jurisdictions&lt;/li&gt;
&lt;li&gt;historical interpretations&lt;/li&gt;
&lt;li&gt;configurable business rules&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;you may not have a data problem.&lt;/p&gt;

&lt;p&gt;You may have a context problem.&lt;/p&gt;

&lt;p&gt;And context is often easier to model than truth.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Originally inspired by architectural challenges encountered while building SAGE, an AI-powered platform for Western Geomancy and Indian Ramal traditions.&lt;/em&gt;&lt;/p&gt;




&lt;p&gt;I'm the founder of SAGE (School of Ancient Geomantic Education), where we're building AI-powered systems for Western Geomancy and Indian Ramal. I write about software architecture, knowledge modeling, and the challenges of digitizing historical systems.&lt;/p&gt;

&lt;h2&gt;
  
  
  Further Reading
&lt;/h2&gt;

&lt;p&gt;This article was adapted from a real architectural challenge encountered while building SAGE (School of Ancient Geomantic Education), an AI-powered platform for Western Geomancy and Indian Ramal.&lt;/p&gt;

&lt;p&gt;For the original article and additional discussion, visit:&lt;/p&gt;

&lt;p&gt;👉 &lt;a href="https://www.dotsofdestiny.com/blog-post-conflict-resolution" rel="noopener noreferrer"&gt;https://www.dotsofdestiny.com/blog-post-conflict-resolution&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You can also explore the broader project at:&lt;/p&gt;

&lt;p&gt;👉 &lt;a href="https://www.dotsofdestiny.com" rel="noopener noreferrer"&gt;https://www.dotsofdestiny.com&lt;/a&gt;&lt;/p&gt;

</description>
      <category>architecture</category>
      <category>database</category>
      <category>ai</category>
      <category>webdev</category>
    </item>
  </channel>
</rss>
