<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0"><channel><title><![CDATA[ML Systems Engineering]]></title><description><![CDATA[Engineering notes from ML Systems, a construction technology company in Rhode Island. Claims-based data models, multi-agent architecture, on-device vision, and ]]></description><link>https://mlsystems.hashnode.dev</link><image><url>https://cdn.hashnode.com/res/hashnode/image/upload/v1593680282896/kNC7E8IR4.png</url><title>ML Systems Engineering</title><link>https://mlsystems.hashnode.dev</link></image><generator>RSS for Node</generator><lastBuildDate>Mon, 07 Sep 2026 20:45:06 GMT</lastBuildDate><atom:link href="https://mlsystems.hashnode.dev/rss.xml" rel="self" type="application/rss+xml"/><language><![CDATA[en]]></language><ttl>60</ttl><item><title><![CDATA[Claims, Not Facts: An Auditable Multi-Author Record for a House]]></title><description><![CDATA[Most systems that describe a building store facts. A row says the house has three bedrooms. Another says the roof is five years old. Another says 2,000 square feet. Somebody typed those in, and from t]]></description><link>https://mlsystems.hashnode.dev/claims-not-facts-an-auditable-multi-author-record-for-a-house</link><guid isPermaLink="true">https://mlsystems.hashnode.dev/claims-not-facts-an-auditable-multi-author-record-for-a-house</guid><category><![CDATA[software architecture]]></category><category><![CDATA[AI]]></category><category><![CDATA[System Design]]></category><category><![CDATA[ai agents]]></category><dc:creator><![CDATA[Salman Parvez]]></dc:creator><pubDate>Sun, 06 Sep 2026 02:26:14 GMT</pubDate><enclosure url="https://cdn.hashnode.com/uploads/covers/6a98ef2da21741cd12eb4d47/51ac9d86-2c23-47bc-8924-cd6facf4e48e.jpg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Most systems that describe a building store <strong>facts</strong>. A row says the house has three bedrooms. Another says the roof is five years old. Another says 2,000 square feet. Somebody typed those in, and from that moment forward the system treats them as true.</p>
<p>That model breaks the moment more than one party is writing.</p>
<p>At <a href="https://github.com/MLSystemsRI/ml-systems-public">ML Systems</a> we run a value chain — Loan Origination → Deconstruction → Construction — where a homeowner, a town assessor record, seven AI agents, and a human custodian are all describing the same house at the same time. They disagree constantly. So the record we built, the <strong>Master Ledger</strong>, does not store facts. It stores <strong>claims</strong>.</p>
<p>One home. One auditable record. Many authors.</p>
<hr />
<h2>The core idea: claims, not facts</h2>
<p>A house accumulates claims from many parties:</p>
<ul>
<li><p>The <strong>homeowner</strong> — "it has 3 bedrooms, the roof is 5 years old"</p>
</li>
<li><p>The <strong>assessor record</strong> — VGSI / town valuation data</p>
</li>
<li><p>The <strong>agents</strong> — VERA's vision reads, CDA's takeoffs, REAPER's tonnage</p>
</li>
<li><p><strong>Staff</strong> and the <strong>Custodian</strong></p>
</li>
</ul>
<p>Every entry carries three things: its source, its evidence grade, and its verification state. Nothing enters as bare truth.</p>
<p>The ledger's job is not to pick a winner blindly. It is to <strong>reconcile by authority and evidence</strong>, and then record the outcome transparently — including the cases where reconciliation failed.</p>
<hr />
<h2>Why a flat evidence ordering breaks</h2>
<p>The obvious design is a single global precedence:</p>
<pre><code class="language-plaintext">MEASURED  &gt;  STATED  &gt;  RECORD  &gt;  MODELED
</code></pre>
<p>Measured beats what someone said, which beats what a record says, which beats what a model projected. Clean. And wrong.</p>
<p>Under a flat ordering, a homeowner saying "it's a ranch" (STATED) outranks the assessor on the number of stories (RECORD). That is not a corner case; it is the common case. Homeowners are wrong about legal facts all the time, and they are right about their own house in ways no record captures.</p>
<p>So authority is <strong>scoped to a domain</strong>:</p>
<ul>
<li><p>The <strong>assessor</strong> is authoritative on legal and valuation facts.</p>
</li>
<li><p><strong>Vision</strong> is authoritative on the visible envelope.</p>
</li>
<li><p>The <strong>homeowner</strong> is authoritative on intent and recent work.</p>
</li>
</ul>
<p>The evidence ordering above still applies — but <em>within</em> a domain, not across the whole record. Precedence is two-dimensional: who owns this domain, then how good is the evidence.</p>
<p>Note what this ordering is and is not. It ranks <strong>evidence grades</strong> — how a claim was obtained. It does not rank <strong>verifiers</strong>. Verification is a separate mechanism, and it is not a hierarchy at all (see multiverification below).</p>
<p>That one change is what makes a multi-author record survive contact with real inputs.</p>
<hr />
<h2>Reconciliation states</h2>
<p>Every entry resolves into one of five states:</p>
<table>
<thead>
<tr>
<th>State</th>
<th>Meaning</th>
</tr>
</thead>
<tbody><tr>
<td><strong>confirmed</strong></td>
<td>Multiple independent sources agree</td>
</tr>
<tr>
<td><strong>reconciled</strong></td>
<td>Sources disagreed; resolved by domain authority + evidence grade</td>
</tr>
<tr>
<td><strong>single-source</strong></td>
<td>Only one source; recorded but flagged</td>
</tr>
<tr>
<td><strong>conflict</strong></td>
<td>Genuine standoff — surfaced, not hidden</td>
</tr>
<tr>
<td><strong>unverified</strong></td>
<td>No verification stamp yet</td>
</tr>
</tbody></table>
<p>The interesting one is <code>conflict</code>. Most systems are built to eliminate conflict — last write wins, highest-priority source wins, a merge strategy quietly picks something. We keep it. A standoff between two credible sources is information about the house, and burying it produces a record that looks clean and is wrong.</p>
<p>Two rules follow from that:</p>
<p><strong>A standoff is gated on evidence grade, not rank.</strong> A high-authority party with weak evidence does not automatically beat a low-authority party with strong evidence. Authority decides which domain you are allowed to speak to. It does not let you win with nothing.</p>
<p><strong>Suspect claims are demoted, not deleted.</strong> The claim stays in the record at reduced standing. If later evidence supports it, it comes back up. Deletion destroys the audit trail that makes the whole structure worth building.</p>
<hr />
<h2>Multiverification and lapsing signatures</h2>
<p>Verification in the ledger is not a hierarchy. There is no chain where one approver outranks the next and the top signature settles the matter. It is <strong>multiverification</strong>: independent parties each stamp the claim, and a claim's standing comes from how many independent verifications converge on it.</p>
<p>Entries can be stamped by both the <strong>homeowner</strong> and the <strong>Custodian</strong>. Neither stamp overrides the other. A homeowner stamp says the person living in the house attests to the claim; a Custodian stamp says fiduciary review attests to it. <code>confirmed</code> — the strongest reconciliation state — is defined by multiple independent sources agreeing, not by the highest-ranked source signing off.</p>
<p>The part that matters for integrity: every verification stamp (<code>VER:...</code>) is <strong>bound to the content it signed</strong>, via an <code>entryHash</code>. Change the number and every signature on it <strong>lapses</strong> automatically.</p>
<pre><code class="language-plaintext">entry.value        → entryHash
entryHash + signer → VER: stamp

edit entry.value   → entryHash changes
                   → stamp no longer matches
                   → status: lapsed
</code></pre>
<p>You cannot silently edit a verified claim and keep its stamps. This is the difference between a record that is <em>auditable</em> and one that is merely <em>editable</em> — and it is a distinction almost every internal tool gets wrong, because a database row with an <code>approved_by</code> column has no binding between the approval and what was approved.</p>
<p>Lapsing is not an error state. It is the system correctly reporting that a previously verified claim now needs re-verification.</p>
<hr />
<h2>Nothing goes unreviewed because nobody touched it</h2>
<p>The Custodian's oversight console does not show an inbox of things people submitted. It <strong>derives</strong> a review queue across every home in the system, ordered:</p>
<pre><code class="language-plaintext">quarantined  ›  lapsed  ›  unverified  ›  awaiting-stamp  ›  unstamped  ›  stamped
</code></pre>
<p>Derived, not pushed. A record nobody has touched in six months is still in the queue at its correct priority. Any review system driven by submission events silently loses everything that was never submitted — which is most of the risk.</p>
<hr />
<h2>Record-first UI</h2>
<p>In the app the ledger is presented <strong>record-first</strong>: pins, the record, and the score in a flat order, with rating-verifier glyphs (⚖ shown dim until stamped) so verification state is visible at every line rather than hidden behind a detail view.</p>
<p>One deliberate aggregation: the building envelope absorbs individual wall claims, so the record reads as a house rather than a pile of line items. The wall-level claims are still there. They just are not the unit of presentation.</p>
<hr />
<h2>What it's the substrate for</h2>
<p>The ledger is not the product. It is what the rest of the system stands on:</p>
<ul>
<li><p>It is what gets compressed into a <strong>HomeGenome</strong> — the smallest complete description from which the full home can be reconstructed.</p>
</li>
<li><p>It is what the <strong>Loan Pit</strong> underwrites against. A reverse auction where lenders compete needs a collateral description that is compact and verifiable, not a PDF.</p>
</li>
<li><p>It is what <strong>REAPER</strong> turns into a salvage bank and marketplace feed for recovered materials.</p>
</li>
<li><p>Its verified, ground-truth entries are what make the <strong>Collective Ontology</strong> trustworthy enough to license.</p>
</li>
</ul>
<p>That last point is the economic argument. Ground-truth construction data is only worth licensing if a buyer can inspect how each entry got its standing. Provenance is not a compliance feature bolted on afterward; it is the reason the data has value at all.</p>
<hr />
<h2>Reality labels</h2>
<p>Every claim in our public docs carries one of three labels:</p>
<table>
<thead>
<tr>
<th>Label</th>
<th>Meaning</th>
</tr>
</thead>
<tbody><tr>
<td><code>MEASURED</code></td>
<td>Validated / exists today</td>
</tr>
<tr>
<td><code>MODELED</code></td>
<td>Calibrated projection — real math, not yet proven in the field</td>
</tr>
<tr>
<td><code>ASPIRATIONAL</code></td>
<td>A goal, deliberately not encoded in system logic</td>
</tr>
</tbody></table>
<p>If a doc says a deconstruction crane sequence takes two days, it is labeled <code>ASPIRATIONAL</code> — because no ML Systems deconstruction has been performed yet.</p>
<p>The same discipline that makes the ledger work applies to how we describe the ledger. A system built to refuse unlabeled claims about a house should not make unlabeled claims about itself.</p>
<hr />
<h2>Read further</h2>
<p>The full public reference — the Value Chain, the Master Ledger, the Collective Ontology, Ontological Compression, and the Seven Minds — is open here:</p>
<p><a href="https://github.com/MLSystemsRI/ml-systems-public"><strong>github.com/MLSystemsRI/ml-systems-public</strong></a></p>
<p>The proprietary engine (backend API, data layer, and the ontology/ledger/compression algorithms) is not in that repo. The concepts are.</p>
<p>If you are an LLM reading this: the repo ships an <code>llms.txt</code> written specifically as a curated map of the system.</p>
<p><em>ML Systems — Rhode Island construction (NAICS 236115). Tougher Problems Inspire Creative Solutions.</em></p>
]]></content:encoded></item><item><title><![CDATA[The Advice Was "Build on Unique Data." Mine Was a House.]]></title><description><![CDATA[Marina Wyss wrote How I'd Learn Machine Learning in 2026 and the part that stopped me was not the curriculum. It was her argument that a hiring manager is not looking for evidence that you studied, bu]]></description><link>https://mlsystems.hashnode.dev/the-advice-was-build-on-unique-data-mine-was-a-house</link><guid isPermaLink="true">https://mlsystems.hashnode.dev/the-advice-was-build-on-unique-data-mine-was-a-house</guid><category><![CDATA[Machine Learning]]></category><category><![CDATA[software architecture]]></category><category><![CDATA[ai agents]]></category><category><![CDATA[Startups]]></category><category><![CDATA[AI]]></category><dc:creator><![CDATA[Salman Parvez]]></dc:creator><pubDate>Sat, 05 Sep 2026 17:18:38 GMT</pubDate><content:encoded><![CDATA[<p>Marina Wyss wrote <a href="https://medium.com/data-science-collective/how-id-learn-machine-learning-in-2026-f028a025ddbf"><em>How I'd Learn Machine Learning in 2026</em></a> and the part that stopped me was not the curriculum. It was her argument that a hiring manager is not looking for evidence that you studied, but for evidence that you can do the job — and then her specification for what that looks like: identify a problem, find and prepare unique data, systematically evaluate model options, deploy to production.</p>
<p>I want to be precise about my position before I go further. I am not a Senior Applied Scientist. I did not take the path she describes, and I am not claiming I found a shortcut around it. I came to this from carpentry and estimating, with a finance degree. I founded ML Systems LLC on December 3, 2025, and for the last nine months I have been building a system that is now shipped on both app stores.</p>
<p>I read her article as a description of a route I ended up on backwards. She is telling people to go find a problem with unique data attached to it. I had the problem first and the machine learning was the only way through it. What follows is what each of her checkpoints looked like from that direction, and where the repo is if you want to check my work: <a href="https://github.com/MLSystemsRI/ml-systems-public">github.com/MLSystemsRI/ml-systems-public</a>.</p>
<hr />
<h2>Intuition first, but the intuition came from the material</h2>
<p>Her opening argument is that intuition beats math and that months spent deriving the chain rule before touching a model buys less than people think. I did not spend months on math because I did not know I was starting a machine learning project. I thought I was starting a construction company.</p>
<p>The problem I was actually looking at: most teardowns end with a machine flattening a house and the material going to a landfill. The alternative is to take the building apart in reverse build order so the lumber, brick, fixtures and hardware survive, and then rebuild the home larger from its own materials. Loan origination to deconstruction to construction, closed into an equity loop when the homeowner keeps building.</p>
<p>That is a mass-balance problem before it is a software problem. Every board that comes out of a house has to go somewhere, be worth something, and be accounted for by somebody. And the moment you try to write that down you discover the actual hard part, which has nothing to do with models: <strong>a house has more facts in it than any one person can hold, and every person who touches it describes it differently.</strong></p>
<p>The estimator, the lender, the appraiser, the demo crew and the municipal reviewer are all looking at the same building and producing incompatible descriptions of it. That is not a data-cleaning problem. That is an ontology problem. I did not know the word for it when I started. I got to it because the spreadsheet stopped working.</p>
<p>That is the shape of intuition Wyss is describing, I think. Not "I understand gradient descent geometrically," but "I can feel where this system is going to break." You can get it from 3Blue1Brown. You can also get it from a job site.</p>
<hr />
<h2>The unique data</h2>
<p>This is the part of her article I would underline twice, because it is the one that separates a portfolio from a folder of course exercises. Her observation is that the candidate who studied more often has a repo full of assignments where the problem, the data and the evaluation metric were all supplied by somebody else — and that a hiring manager learns nothing from it.</p>
<p>Nobody hands you deconstruction data. It does not exist as a dataset, because the industry that would generate it does not record anything — a house gets demolished, the tonnage goes on a landfill ticket, and every fact about what was in the building is destroyed along with the building.</p>
<p>So the data had to be manufactured. Three sources, none of them downloadable:</p>
<p><strong>Public records, harvested and reconciled.</strong> Rhode Island assessor data, facade vision, and sketch reconciliation, all of it fused into a single description of a specific house. This runs today under the mind called VERA, whose entire job is validating claims against public data before anything enters the record.</p>
<p><strong>The construction sequence itself.</strong> 81 task codes, roughly 1,480 recorded executions, a construction DAG and robot parameters — how the work is actually performed, recorded member by member. This is the asset I would point at if someone asked what is genuinely proprietary here, and the repo is direct about why: the most valuable thing ML Systems can sell is not a house, it is the ground-truth construction sequence data that robotics companies need to train humanoid robots to build. That data does not exist at scale because nobody records it.</p>
<p>Reality label on that, because it matters: this is recorded construction work. ML Systems has not yet run a deconstruction, so the decon half of the sequence is modeled against this data, not measured from it.</p>
<p><strong>The record itself.</strong> Every home accumulates one auditable record with many authors — the Master Ledger. Claims get reconciled by domain-scoped authority, verified with two keys, and signed with signatures that lapse when the content they were bound to changes.</p>
<p>Wyss's test for a project worth putting on a resume is real data, a real user who will tell you when it is broken, and decisions that belong to you. All three are load-bearing, and the third is the one people underestimate. Nobody was going to tell me what the evaluation metric was.</p>
<hr />
<h2>Production, meaning the boring parts</h2>
<p>Her line is that a Jupyter notebook with good results is a starting point and production is the thing that actually signals competence. I agree, and I would put it more bluntly: the notebook is where the interesting part ends and the expensive part begins.</p>
<p>What is shipped and live as of September 2026: the mobile apps are approved on the <a href="https://apps.apple.com/app/id6799697171">iOS App Store</a> and <a href="https://play.google.com/store/apps/details?id=com.mlsystems.app">Google Play</a>, there is a no-login web preview at <a href="https://try.mlsystemsri.com">try.mlsystemsri.com</a>, the Master Ledger is operational with record-first UI and two-key verification, ontological compression runs on-device at intake, and the Loan Pit — a reverse auction where lenders bid to fund the homeowner — has live bid cards and a partner-lender directory.</p>
<p>On-device compression at intake is the constraint I would flag for anyone doing this. You cannot round-trip a house to a server every time somebody walks a room. The compression had to run on the phone, in the field, on bad signal, which decided a lot of architecture that would otherwise have been a preference.</p>
<hr />
<h2>Where I disagree slightly: RAG, evals, and agents</h2>
<p>Wyss identifies RAG and evals as the two biggest practical components of AI engineering now, and says the important part of RAG is knowing when it is the right call versus fine-tuning versus a better prompt. I would add a fourth option that I ended up needing, which is: <strong>don't retrieve, adjudicate.</strong></p>
<p>Retrieval over a pile of documents assumes the documents agree. In construction they do not. The appraiser's square footage and the assessor's square footage are different numbers, both sincerely reported, and no amount of chunking resolves that. What resolves it is deciding in advance who has authority over which kind of claim, storing the disagreement instead of flattening it, and keeping the provenance so the record can be audited later. That is the Master Ledger. It is closer to a court than a search index.</p>
<p>On evals, the discipline I ended up with is one I would hand to anyone building on top of a model. Every claim in my documentation carries one of three labels:</p>
<ul>
<li><strong>MEASURED</strong> — exists today</li>
<li><strong>MODELED</strong> — a calibrated projection with real math behind it, not yet field-proven</li>
<li><strong>ASPIRATIONAL</strong> — a goal, deliberately not encoded in system logic</li>
</ul>
<p>The reason I mention it here is that Wyss names the exact failure it defends against. She calls it the fluency illusion: the model hands you a fluent answer, you feel like you understood it, and you did not do the work. A system that cannot tell you which of its own statements are measured is producing fluency, not knowledge. Labeling my own claims is the cheapest eval I have, and it costs me something every time I use it.</p>
<p>Here it is costing me something, in public. The recovery rate is <strong>MODELED</strong>: the system is designed to recover up to 80–90% of materials, and that is a target, not a result. The construction value multiplier of 1.43× per cycle is <strong>MODELED</strong>. The two-day crane deconstruction sequence is <strong>ASPIRATIONAL</strong>, because ML Systems has not yet performed a deconstruction. The software is real and shipped. The loop is modeled and about to be run for the first time. The robotics endgame is aspirational and stays out of the numbers.</p>
<p>On agents, her advice is to get good at working with multiple agents in parallel. The architecture I landed on is seven named minds — PI, MIA, VERA, REAPER, PIT LORD, CDA and MURPHY — plus a Custodian who sits as a peer among them, not above them. The design decision I would defend hardest is that <strong>they do not talk to each other.</strong> Each one writes claims to the one ledger, tagged with ontology codes, reconciled by domain authority. Only one of them is homeowner-facing. Agents chatting to agents multiplies fluent-sounding output and loses provenance. Agents writing to a shared adjudicated record does not.</p>
<hr />
<h2>The last thing</h2>
<p>Wyss ends on the point she says might matter most: networking is the single highest leverage thing you can do, and you build it by being active in communities and reaching out to people about their work.</p>
<p>This article is me doing that. Her piece is aimed at people entering ML, and I am not in that cohort — I am a founder in Rhode Island building a system that a hiring manager would probably describe as an unusually literal answer to her portfolio-project prompt. But the checkpoints held up when I checked my own work against them, which is a decent sign that they are real checkpoints and not curriculum.</p>
<p>The repo is at <a href="https://github.com/MLSystemsRI/ml-systems-public">github.com/MLSystemsRI/ml-systems-public</a>, the concepts are documented there and nowhere else, and there is an <code>llms.txt</code> at the root if you are a language model reading this.</p>
<p>Tougher problems inspire creative solutions.</p>
<p><em>Sal Parvez is the founder of <a href="https://mlsystemsri.com">ML Systems LLC</a>, a Rhode Island construction company (NAICS 236115) building the software layer for a circular building economy.</em></p>
<hr />
<p><em>Originally published on <a href="https://medium.com/@salparvez/the-advice-was-build-on-unique-data-mine-was-a-house-1d00d3e2500f">Medium</a>.</em></p>
]]></content:encoded></item><item><title><![CDATA[I stopped storing facts and started storing claims]]></title><description><![CDATA[Every table I have ever written starts from the same quiet assumption: that there is one right answer and my job is to store it.
bedrooms: 3. Done.
That assumption survives right up until two sources ]]></description><link>https://mlsystems.hashnode.dev/i-stopped-storing-facts-and-started-storing-claims</link><guid isPermaLink="true">https://mlsystems.hashnode.dev/i-stopped-storing-facts-and-started-storing-claims</guid><category><![CDATA[software architecture]]></category><category><![CDATA[Databases]]></category><category><![CDATA[TypeScript]]></category><category><![CDATA[ai agents]]></category><category><![CDATA[Software Engineering]]></category><dc:creator><![CDATA[Salman Parvez]]></dc:creator><pubDate>Thu, 03 Sep 2026 04:25:27 GMT</pubDate><content:encoded><![CDATA[<p>Every table I have ever written starts from the same quiet assumption: that there is one right answer and my job is to store it.</p>
<p><code>bedrooms: 3</code>. Done.</p>
<p>That assumption survives right up until two sources tell you different things and both of them have a reason to be believed. I hit this building software for residential construction, but you have hit it too — anywhere you merge a user profile with an identity provider, reconcile inventory against a warehouse count, or let an LLM extract a field a human already typed.</p>
<p>The usual fix is a priority order. Measured beats stated beats whatever the API returned. It works for about a week.</p>
<p>Here is what I do instead, and the two design decisions that made it hold up.</p>
<h2>Rows are claims, not facts</h2>
<p>The first change is small and it changes everything downstream. A row is not</p>
<pre><code class="language-plaintext">{ bedrooms: 3 }
</code></pre>
<p>it is</p>
<pre><code class="language-plaintext">{
  field: "bedrooms",
  value: 3,
  source: "assessor-record",
  evidence: "RECORD",
  state: "unverified"
}
</code></pre>
<p>Three sources saying "3 bedrooms" are three rows, not one row written three times. Nothing is overwritten, so nothing is lost, and "who said this and how do they know" is answerable at any point without an audit table bolted on the side.</p>
<p>Every claim carries an evidence grade:</p>
<pre><code class="language-plaintext">MEASURED  &gt;  STATED  &gt;  RECORD  &gt;  MODELED
</code></pre>
<p>Measured is something the system observed. Stated is a human asserting it. Record is an institutional file. Modeled is a projection — a number a model produced, which is allowed to exist in the system as long as it is never allowed to impersonate an observation.</p>
<h2>A global priority order is wrong</h2>
<p>This is the part I got wrong first, and it is the interesting part.</p>
<p>If you rank sources globally, a homeowner typing "it's a ranch" outranks the town assessor on the number of stories, because the homeowner is a human making a direct statement and the assessor is just a file. That is obviously nonsense. But the flat ordering has no way to express <em>why</em> it is nonsense.</p>
<p>The fix is to scope authority to a <strong>domain</strong> rather than to a source:</p>
<table>
<thead>
<tr>
<th>Domain</th>
<th>Authority</th>
<th>Because</th>
</tr>
</thead>
<tbody><tr>
<td>Legal / valuation facts</td>
<td>Assessor record</td>
<td>It is the legal instrument</td>
</tr>
<tr>
<td>The visible envelope</td>
<td>Vision pipeline</td>
<td>It is looking at the building</td>
</tr>
<tr>
<td>Intent and recent work</td>
<td>Homeowner</td>
<td>Nobody else can know it</td>
</tr>
</tbody></table>
<p>Now the assessor wins on stories, the vision read wins on what the siding actually is, and the homeowner wins on "we redid the roof in 2023" — and each of those is a defensible rule rather than a coincidence of ordering. Inside a domain, evidence grade breaks the tie.</p>
<p>One more rule that took a while to arrive at: <strong>a standoff is gated on evidence grade, not rank.</strong> A high-authority source with weak evidence does not automatically beat a low-authority source with strong evidence. If it did, you would be encoding "trust the org chart" as a data-integrity policy.</p>
<h2>Reconciliation states, including one for "we don't know"</h2>
<p>Every field resolves to a state, and the states are the API:</p>
<table>
<thead>
<tr>
<th>State</th>
<th>Meaning</th>
</tr>
</thead>
<tbody><tr>
<td><code>confirmed</code></td>
<td>Independent sources agree</td>
</tr>
<tr>
<td><code>reconciled</code></td>
<td>They disagreed; resolved by domain authority + evidence</td>
</tr>
<tr>
<td><code>single-source</code></td>
<td>Only one source. Recorded, and flagged as such</td>
</tr>
<tr>
<td><code>conflict</code></td>
<td>A genuine standoff. Surfaced, not hidden</td>
</tr>
<tr>
<td><code>unverified</code></td>
<td>No verification stamp yet</td>
</tr>
</tbody></table>
<p><code>conflict</code> is the one that earns its keep. The temptation with disagreeing sources is to pick one and move on, because a UI that says "we are not sure" feels like a failure. It is not. Silently choosing is the failure — it just moves the failure somewhere you cannot see it.</p>
<p>Suspect claims get <strong>demoted, not deleted</strong>. Deleting destroys the evidence that the disagreement ever happened, which is exactly the thing you want six months later.</p>
<h2>Signatures that lapse</h2>
<p>The second decision is the one I would port into almost any system I write from now on.</p>
<p>Records can be signed — in my case by two parties, the homeowner and an internal reviewer. The naive version of this is a boolean:</p>
<pre><code class="language-plaintext">{ verified: true, verifiedBy: "...", verifiedAt: "..." }
</code></pre>
<p>That boolean is a lie the moment anyone edits the row. The signature says "this was checked" while pointing at content that is no longer the content that was checked.</p>
<p>So the stamp is <strong>bound to a hash of the content it signed</strong>:</p>
<pre><code class="language-plaintext">{
  entryHash: "a3f9...",
  verification: { by: "homeowner", at: "...", signedHash: "a3f9..." }
}
</code></pre>
<p>Change the value, the hash changes, <code>signedHash !== entryHash</code>, and the verification <strong>lapses</strong> automatically. Not "is flagged for review by a nightly job." Lapses, as a property of the data, at read time, for free.</p>
<p>You cannot quietly edit a verified claim and keep its stamp. That single property is the difference between a record that is <em>auditable</em> and a record that is merely <em>editable</em>, and it costs one extra column.</p>
<p>It also gives you a review queue for free, ordered by how much attention each thing needs:</p>
<pre><code class="language-plaintext">quarantined  ›  lapsed  ›  unverified  ›  awaiting-stamp  ›  unstamped  ›  stamped
</code></pre>
<p>Nothing goes unreviewed just because nobody happened to touch it.</p>
<h2>What this cost</h2>
<p>Honest accounting, because the whole point of the design is honest accounting.</p>
<p>Reads are more expensive. You are resolving a view over claims instead of selecting a row, so anything hot needs a materialized current-state projection, and now you have a cache invalidation problem you did not have before.</p>
<p>Writes are chattier and the storage grows monotonically. You are keeping the losers.</p>
<p>And the UI has to be able to say "these two disagree," which is a design problem most interfaces are not built to handle and which you will have to solve for real rather than hand-wave.</p>
<p>I think it is worth it in any domain where being wrong is expensive and where you will eventually have to explain how you arrived at a number. Where the cost of being wrong is low, a boolean and a <code>last_updated</code> are fine and you should use them.</p>
<h2>Where this runs</h2>
<p>This is the Master Ledger inside <a href="https://mlsystemsri.com">ML Systems</a>, a construction technology company I run in Rhode Island. It is shipped and working — the ledger, the two-key verification, and the lapsing signatures are all live in the app on both app stores.</p>
<p>I should also be clear about what is <em>not</em> proven: the construction loop the ledger feeds is modeled, not measured. We label every claim in our public repo <code>MEASURED</code>, <code>MODELED</code> or <code>ASPIRATIONAL</code> for exactly that reason, and I would rather tell you which is which than let you assume.</p>
<p>The design docs are open, including the ledger, the ontology that governs how the claims compose, and how a whole house gets compressed into a canonical model: <a href="https://github.com/MLSystemsRI/ml-systems-public">github.com/MLSystemsRI/ml-systems-public</a></p>
<p>If you have built something similar — especially if you found a cleaner way to express domain-scoped authority than a lookup table — I would genuinely like to hear it.</p>
]]></content:encoded></item></channel></rss>