<?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>I Found a Deterministic State Machine Hidden in a 1,000-Year-Old Indian Knowledge System</title>
      <dc:creator>Arvind Jolly</dc:creator>
      <pubDate>Fri, 26 Jun 2026 05:42:35 +0000</pubDate>
      <link>https://dev.to/arvindjolly/i-found-a-deterministic-state-machine-hidden-in-a-1000-year-old-indian-knowledge-system-2al5</link>
      <guid>https://dev.to/arvindjolly/i-found-a-deterministic-state-machine-hidden-in-a-1000-year-old-indian-knowledge-system-2al5</guid>
      <description>&lt;p&gt;&lt;em&gt;Sometimes the most elegant software architecture was designed centuries before software existed.&lt;/em&gt;&lt;/p&gt;




&lt;p&gt;When I began implementing &lt;strong&gt;Indian Ramal Shastra&lt;/strong&gt; (an Indian adaptation of Arabic geomancy) as a Python application, I expected to spend most of my time translating historical rules into code.&lt;/p&gt;

&lt;p&gt;Instead, I stumbled upon something I never expected.&lt;/p&gt;

&lt;p&gt;Buried inside a thousand-year-old knowledge system was what every software engineer would immediately recognize as a &lt;strong&gt;deterministic finite state machine&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Not a metaphor.&lt;/p&gt;

&lt;p&gt;An actual state machine.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Discovery
&lt;/h2&gt;

&lt;p&gt;One challenge in Ramal is determining the &lt;strong&gt;temporal behavior&lt;/strong&gt; of an outcome.&lt;/p&gt;

&lt;p&gt;Is an event approaching?&lt;/p&gt;

&lt;p&gt;Is it moving away?&lt;/p&gt;

&lt;p&gt;Will it remain stable?&lt;/p&gt;

&lt;p&gt;Or is it inherently unstable?&lt;/p&gt;

&lt;p&gt;Modern software engineers would probably model this using an enum.&lt;/p&gt;

&lt;p&gt;The Ramal tradition did exactly that—long before programming languages existed.&lt;/p&gt;

&lt;p&gt;Every one of its sixteen symbols belongs permanently to one of only four states.&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;Gati&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Enum&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;DAKHIL&lt;/span&gt;   &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Entering&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
    &lt;span class="n"&gt;KHARIJ&lt;/span&gt;   &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Exiting&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
    &lt;span class="n"&gt;SABIT&lt;/span&gt;    &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Stable&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
    &lt;span class="n"&gt;MUNQALEB&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Transforming&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That's it.&lt;/p&gt;

&lt;p&gt;Every possible input maps to exactly one state.&lt;/p&gt;

&lt;p&gt;No ambiguity.&lt;/p&gt;

&lt;p&gt;No probability.&lt;/p&gt;

&lt;p&gt;No fuzzy inference.&lt;/p&gt;

&lt;h2&gt;
  
  
  A Static Lookup Table
&lt;/h2&gt;

&lt;p&gt;The implementation ended up looking surprisingly modern.&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="n"&gt;STATE_TABLE&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;1211&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Gati&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;DAKHIL&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;1121&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Gati&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;KHARIJ&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;2222&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Gati&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;SABIT&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;1111&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Gati&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;MUNQALEB&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="c1"&gt;# ...
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The engine doesn't &lt;em&gt;calculate&lt;/em&gt; the state.&lt;/p&gt;

&lt;p&gt;It simply performs a lookup.&lt;/p&gt;

&lt;p&gt;The state is immutable because tradition already assigned it centuries ago.&lt;/p&gt;

&lt;p&gt;Once the state is known, downstream behavior becomes deterministic.&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;if&lt;/span&gt; &lt;span class="n"&gt;state&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="n"&gt;Gati&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;DAKHIL&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;timing&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;1–7 days&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;

&lt;span class="k"&gt;elif&lt;/span&gt; &lt;span class="n"&gt;state&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="n"&gt;Gati&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;KHARIJ&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;timing&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;2–4 weeks&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;

&lt;span class="k"&gt;elif&lt;/span&gt; &lt;span class="n"&gt;state&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="n"&gt;Gati&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;SABIT&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;timing&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;2–6 months&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;

&lt;span class="k"&gt;else&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;timing&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;7–21 days&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you've written protocol handlers, parsers, workflow engines, or embedded software, this pattern probably feels familiar.&lt;/p&gt;

&lt;h2&gt;
  
  
  What Makes It Interesting
&lt;/h2&gt;

&lt;p&gt;The remarkable part isn't that ancient scholars classified symbolic figures.&lt;/p&gt;

&lt;p&gt;Many traditions do that.&lt;/p&gt;

&lt;p&gt;The remarkable part is &lt;strong&gt;how&lt;/strong&gt; they classified them.&lt;/p&gt;

&lt;p&gt;The system has several properties we still value in software architecture today:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Deterministic&lt;/li&gt;
&lt;li&gt;Exhaustive&lt;/li&gt;
&lt;li&gt;Immutable&lt;/li&gt;
&lt;li&gt;Composable&lt;/li&gt;
&lt;li&gt;Easy to verify&lt;/li&gt;
&lt;li&gt;No undefined states&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Every possible input is handled.&lt;/p&gt;

&lt;p&gt;Every input produces exactly one state.&lt;/p&gt;

&lt;p&gt;Nothing is left undefined.&lt;/p&gt;

&lt;h2&gt;
  
  
  Beyond the State Machine
&lt;/h2&gt;

&lt;p&gt;While implementing the engine, I noticed something even more interesting.&lt;/p&gt;

&lt;p&gt;The four movement states aren't the only classification.&lt;/p&gt;

&lt;p&gt;Each figure also carries independent attributes describing its temperament and behavioral nature.&lt;/p&gt;

&lt;p&gt;Instead of exploding into dozens of special cases, these independent dimensions compose cleanly into what is essentially a multidimensional domain model.&lt;/p&gt;

&lt;p&gt;From a software design perspective, this is surprisingly elegant.&lt;/p&gt;

&lt;h2&gt;
  
  
  Ancient Domain-Driven Design?
&lt;/h2&gt;

&lt;p&gt;One observation kept occurring to me while writing the engine.&lt;/p&gt;

&lt;p&gt;The original practitioners obviously weren't thinking about enums, finite automata, or type systems.&lt;/p&gt;

&lt;p&gt;Yet they arrived at a structure that maps naturally onto all of them.&lt;/p&gt;

&lt;p&gt;The implementation required remarkably little interpretation because the underlying model was already highly structured.&lt;/p&gt;

&lt;p&gt;Sometimes good architecture simply transcends technology.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why I Wrote About It
&lt;/h2&gt;

&lt;p&gt;This isn't really an article about divination.&lt;/p&gt;

&lt;p&gt;It's an article about discovering computational thinking in an unexpected place.&lt;/p&gt;

&lt;p&gt;As developers, we're accustomed to believing that formal state modeling belongs to modern computer science.&lt;/p&gt;

&lt;p&gt;But occasionally history reminds us that people were building elegant rule-based systems long before computers existed.&lt;/p&gt;

&lt;p&gt;And that's fascinating.&lt;/p&gt;




&lt;h2&gt;
  
  
  Read the Complete Technical Breakdown
&lt;/h2&gt;

&lt;p&gt;The full article includes:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;the complete 16-figure state table&lt;/li&gt;
&lt;li&gt;the four canonical movement states&lt;/li&gt;
&lt;li&gt;Python implementation details&lt;/li&gt;
&lt;li&gt;timing engine logic&lt;/li&gt;
&lt;li&gt;coherence scoring&lt;/li&gt;
&lt;li&gt;structural invariants&lt;/li&gt;
&lt;li&gt;why the model is effectively a deterministic finite state machine&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;You can read the complete article here:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;a href="https://dotsofdestiny.com/blog-post-ramal-state-machine.html" rel="noopener noreferrer"&gt;https://dotsofdestiny.com/blog-post-ramal-state-machine.html&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;I'm curious whether you've encountered other historical systems whose architecture resembles modern software design. I'd love to hear your examples in the comments.&lt;/p&gt;

</description>
      <category>programming</category>
      <category>python</category>
      <category>computerscience</category>
      <category>software</category>
    </item>
    <item>
      <title>Building a High-Performance Progressive Web App Without React or Next.js</title>
      <dc:creator>Arvind Jolly</dc:creator>
      <pubDate>Mon, 22 Jun 2026 11:13:19 +0000</pubDate>
      <link>https://dev.to/arvindjolly/building-an-offline-first-progressive-web-app-without-react-or-nextjs-hac</link>
      <guid>https://dev.to/arvindjolly/building-an-offline-first-progressive-web-app-without-react-or-nextjs-hac</guid>
      <description>&lt;p&gt;&lt;em&gt;Lessons learned from improving performance, caching, and user experience in a production web application.&lt;/em&gt;&lt;/p&gt;

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

&lt;p&gt;When we set out to build &lt;strong&gt;SAGE (School of Ancient Geomantic Education)&lt;/strong&gt;, our focus was not initially on Progressive Web Apps.&lt;/p&gt;

&lt;p&gt;SAGE combines traditional systems such as Western Geomancy and Indian Ramal Shastra with modern web technologies, educational resources, interactive calculators, and AI-assisted interpretation.&lt;/p&gt;

&lt;p&gt;As the platform evolved, performance, reliability, and user experience became increasingly important concerns.&lt;/p&gt;

&lt;p&gt;Our users access the platform from a wide variety of devices and network conditions. Some use desktop computers with fast broadband connections. Others rely on mobile networks where latency and bandwidth can vary significantly.&lt;/p&gt;

&lt;p&gt;We wanted the experience to feel fast, responsive, and dependable regardless of connection quality.&lt;/p&gt;

&lt;p&gt;That led us to explore:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Service Workers&lt;/li&gt;
&lt;li&gt;Intelligent caching strategies&lt;/li&gt;
&lt;li&gt;Firebase Hosting optimizations&lt;/li&gt;
&lt;li&gt;Progressive Web App technologies&lt;/li&gt;
&lt;li&gt;Performance-focused UX design&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The goal was not to create a fully offline oracle. AI-assisted readings continue to require backend services and network connectivity.&lt;/p&gt;

&lt;p&gt;Instead, the objective was to improve performance, reduce unnecessary network requests, create a more resilient user experience, and make the platform feel more like a modern application than a traditional website.&lt;/p&gt;

&lt;p&gt;This is the story of how we transformed a straightforward HTML + Firebase Hosting application into a faster, more polished Progressive Web App—without React, Next.js, or heavyweight build pipelines.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Core Principle: Treat the Service Worker as a Router
&lt;/h2&gt;

&lt;p&gt;Many PWA tutorials present caching strategies as isolated techniques:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Cache-first&lt;/li&gt;
&lt;li&gt;Network-first&lt;/li&gt;
&lt;li&gt;Stale-while-revalidate&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In practice, a production application usually needs several of them simultaneously.&lt;/p&gt;

&lt;p&gt;The most useful mental model we found was to think of the service worker as a routing layer.&lt;/p&gt;

&lt;p&gt;Different content types receive different treatment.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Content&lt;/th&gt;
&lt;th&gt;Strategy&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Images, CSS, fonts, static JavaScript&lt;/td&gt;
&lt;td&gt;Cache-first&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;HTML documents&lt;/td&gt;
&lt;td&gt;Network-first&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;API requests&lt;/td&gt;
&lt;td&gt;Pass-through&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Configuration modules&lt;/td&gt;
&lt;td&gt;Always fresh&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;The important question is not:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Which caching strategy should I use?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The important question is:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Which caching strategy should this particular resource use?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Once we adopted that mindset, the service worker became dramatically easier to reason about.&lt;/p&gt;

&lt;h2&gt;
  
  
  Public Content and Private Content Are Different Problems
&lt;/h2&gt;

&lt;p&gt;One mistake I see frequently in PWA discussions is treating all pages equally.&lt;/p&gt;

&lt;p&gt;They aren't.&lt;/p&gt;

&lt;p&gt;Some pages are:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Public&lt;/li&gt;
&lt;li&gt;Anonymous&lt;/li&gt;
&lt;li&gt;Safe to cache&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Others are:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;User-specific&lt;/li&gt;
&lt;li&gt;Session-aware&lt;/li&gt;
&lt;li&gt;Privacy-sensitive&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The boundary matters.&lt;/p&gt;

&lt;p&gt;For example, serving a stale public calculator page is usually harmless.&lt;/p&gt;

&lt;p&gt;Serving cached user-specific content to the wrong session is not.&lt;/p&gt;

&lt;p&gt;Our solution was simple:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Public pages can be pre-cached.&lt;/li&gt;
&lt;li&gt;Session-dependent pages are excluded from pre-caching.&lt;/li&gt;
&lt;li&gt;Sensitive content is always fetched fresh.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The result is a much safer offline experience.&lt;/p&gt;

&lt;h2&gt;
  
  
  Never Cache the Service Worker
&lt;/h2&gt;

&lt;p&gt;If there is one rule worth remembering, it is this:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Do not aggressively cache your service worker.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The service worker controls your entire update mechanism.&lt;/p&gt;

&lt;p&gt;If the browser becomes stuck with an old service worker, every future deployment becomes harder.&lt;/p&gt;

&lt;p&gt;Static assets can be immutable.&lt;/p&gt;

&lt;p&gt;The service worker cannot.&lt;/p&gt;

&lt;p&gt;Treat it as the control plane for your application.&lt;/p&gt;

&lt;h2&gt;
  
  
  Build an Escape Hatch
&lt;/h2&gt;

&lt;p&gt;Eventually, every production application encounters one of these:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A bad deployment&lt;/li&gt;
&lt;li&gt;Corrupted cache state&lt;/li&gt;
&lt;li&gt;An update bug&lt;/li&gt;
&lt;li&gt;A broken service worker&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;When that happens, users should not need to clear browser data manually.&lt;/p&gt;

&lt;p&gt;We implemented a simple versioning mechanism that can:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Detect an application version change&lt;/li&gt;
&lt;li&gt;Unregister outdated service workers&lt;/li&gt;
&lt;li&gt;Trigger a clean reload&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Think of it as an emergency recovery procedure.&lt;/p&gt;

&lt;p&gt;You may never need it.&lt;/p&gt;

&lt;p&gt;When you do need it, you'll be glad it exists.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why We Chose localStorage Instead of IndexedDB
&lt;/h2&gt;

&lt;p&gt;This decision often surprises developers.&lt;/p&gt;

&lt;p&gt;IndexedDB is usually presented as the "correct" storage solution for PWAs.&lt;/p&gt;

&lt;p&gt;For large datasets, that's true.&lt;/p&gt;

&lt;p&gt;For our use case, it wasn't.&lt;/p&gt;

&lt;p&gt;The application only needed to store:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Small pieces of user state&lt;/li&gt;
&lt;li&gt;Temporary workflow data&lt;/li&gt;
&lt;li&gt;Lightweight JSON payloads&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Each payload was only a few kilobytes.&lt;/p&gt;

&lt;p&gt;The benefits of localStorage were compelling:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Simplicity&lt;/li&gt;
&lt;li&gt;Synchronous access&lt;/li&gt;
&lt;li&gt;No schema management&lt;/li&gt;
&lt;li&gt;Minimal implementation complexity&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Could IndexedDB have worked?&lt;/p&gt;

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

&lt;p&gt;Would it have improved the user experience?&lt;/p&gt;

&lt;p&gt;Not meaningfully.&lt;/p&gt;

&lt;p&gt;Sometimes the simplest solution is the right solution.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Most Overlooked Performance Problem: Fonts
&lt;/h2&gt;

&lt;p&gt;Many performance discussions focus on JavaScript bundles.&lt;/p&gt;

&lt;p&gt;In our case, fonts were the bigger challenge.&lt;/p&gt;

&lt;p&gt;The application supports multiple writing systems, including:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Latin&lt;/li&gt;
&lt;li&gt;Devanagari&lt;/li&gt;
&lt;li&gt;Arabic&lt;/li&gt;
&lt;li&gt;Japanese&lt;/li&gt;
&lt;li&gt;Chinese&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Without careful loading strategies, typography can easily become the largest source of perceived latency.&lt;/p&gt;

&lt;p&gt;Three techniques made the difference:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Using &lt;code&gt;display=swap&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Adding preconnect hints&lt;/li&gt;
&lt;li&gt;Caching font resources after the first visit&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;After the initial load, typography effectively became free.&lt;/p&gt;

&lt;h2&gt;
  
  
  Offline UX Is More Important Than Offline Technology
&lt;/h2&gt;

&lt;p&gt;Most developers focus on the technical side of offline support.&lt;/p&gt;

&lt;p&gt;Users don't care about your caching strategy.&lt;/p&gt;

&lt;p&gt;They care about what happens when connectivity disappears.&lt;/p&gt;

&lt;p&gt;When a page isn't available offline, users should never encounter a browser error screen.&lt;/p&gt;

&lt;p&gt;Instead, provide:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A branded fallback page&lt;/li&gt;
&lt;li&gt;Clear messaging&lt;/li&gt;
&lt;li&gt;A recovery path&lt;/li&gt;
&lt;li&gt;Consistent visual identity&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The goal is not merely functionality.&lt;/p&gt;

&lt;p&gt;The goal is preserving trust.&lt;/p&gt;

&lt;h2&gt;
  
  
  Fast Applications Need Feedback
&lt;/h2&gt;

&lt;p&gt;An unexpected challenge emerged once everything was cached.&lt;/p&gt;

&lt;p&gt;The application became extremely fast.&lt;/p&gt;

&lt;p&gt;Page transitions often completed in under 100 milliseconds.&lt;/p&gt;

&lt;p&gt;Users interpreted this as abrupt rather than responsive.&lt;/p&gt;

&lt;p&gt;The solution wasn't optimization.&lt;/p&gt;

&lt;p&gt;The solution was intentional motion.&lt;/p&gt;

&lt;p&gt;Subtle micro-interactions:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Entry animations&lt;/li&gt;
&lt;li&gt;State indicators&lt;/li&gt;
&lt;li&gt;Ambient visual feedback&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;made the interface feel more polished despite adding virtually no latency.&lt;/p&gt;

&lt;p&gt;This was a reminder that perceived performance and measured performance are not always the same thing.&lt;/p&gt;

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

&lt;p&gt;After deploying and maintaining the application, a few principles stood out:&lt;/p&gt;

&lt;h3&gt;
  
  
  1. Service workers are routing infrastructure
&lt;/h3&gt;

&lt;p&gt;Treat them like routers rather than cache containers.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. Not everything belongs in IndexedDB
&lt;/h3&gt;

&lt;p&gt;Simple state often benefits more from simplicity than scalability.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. Offline experiences are UX problems first
&lt;/h3&gt;

&lt;p&gt;Caching is only the implementation detail.&lt;/p&gt;

&lt;h3&gt;
  
  
  4. Every PWA needs a recovery mechanism
&lt;/h3&gt;

&lt;p&gt;Eventually something will go wrong.&lt;/p&gt;

&lt;p&gt;Plan for it.&lt;/p&gt;

&lt;h3&gt;
  
  
  5. Fast interfaces still need visual feedback
&lt;/h3&gt;

&lt;p&gt;Perceived quality matters as much as measured speed.&lt;/p&gt;

&lt;h3&gt;
  
  
  6. Simplicity scales surprisingly far
&lt;/h3&gt;

&lt;p&gt;For many applications, a lightweight architecture can outperform a far more complex framework-based stack.&lt;/p&gt;

&lt;h2&gt;
  
  
  Final Thoughts
&lt;/h2&gt;

&lt;p&gt;The modern web platform already provides most of the tools needed to build capable offline applications.&lt;/p&gt;

&lt;p&gt;Service Workers, Cache Storage, localStorage, and modern browser APIs are remarkably powerful when combined thoughtfully.&lt;/p&gt;

&lt;p&gt;The biggest lesson wasn't technical.&lt;/p&gt;

&lt;p&gt;It was architectural.&lt;/p&gt;

&lt;p&gt;Offline support works best when it is treated as a product requirement from the beginning rather than an enhancement added later.&lt;/p&gt;

&lt;p&gt;When that happens, the result feels less like a website and more like an application that simply happens to run on the web.&lt;/p&gt;

&lt;h2&gt;
  
  
  A Note on Offline Functionality
&lt;/h2&gt;

&lt;p&gt;The techniques discussed in this article focus primarily on performance optimization, caching, installability, and user experience improvements.&lt;/p&gt;

&lt;p&gt;While certain assets and resources benefit from browser caching, AI-assisted readings and other server-dependent functionality continue to require network connectivity and backend processing.&lt;/p&gt;

&lt;p&gt;The goal was to build a faster and more resilient web experience rather than a fully offline application.&lt;/p&gt;




&lt;p&gt;What has been your biggest challenge building PWAs in production? I'd be interested to hear what strategies have worked (or failed) for you.&lt;/p&gt;

&lt;h2&gt;
  
  
  About the Project
&lt;/h2&gt;

&lt;p&gt;SAGE (School of Ancient Geomantic Education) is a modern geomancy platform that combines traditional Western Geomancy and Indian Ramal Shastra with contemporary software engineering.&lt;/p&gt;

&lt;p&gt;The platform provides:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Free geomantic calculators and educational tools&lt;/li&gt;
&lt;li&gt;Daily oracle readings&lt;/li&gt;
&lt;li&gt;Premium AI-assisted geomantic consultations&lt;/li&gt;
&lt;li&gt;Support for multiple languages&lt;/li&gt;
&lt;li&gt;Offline-capable Progressive Web App functionality&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Explore the project at dotsofdestiny.com and learn more about how ancient symbolic systems can be implemented using modern web technologies.&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>pwa</category>
      <category>javascript</category>
      <category>performance</category>
    </item>
    <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>
