<?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: Elon masai</title>
    <description>The latest articles on DEV Community by Elon masai (@elonmasai7).</description>
    <link>https://dev.to/elonmasai7</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%2F1900803%2F1b9022f9-2f76-4656-8b0d-5eebc7fd2124.png</url>
      <title>DEV Community: Elon masai</title>
      <link>https://dev.to/elonmasai7</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/elonmasai7"/>
    <language>en</language>
    <item>
      <title>git-ofrenda: An Ofrenda for Deleted Code</title>
      <dc:creator>Elon masai</dc:creator>
      <pubDate>Thu, 29 Oct 2026 16:41:16 +0000</pubDate>
      <link>https://dev.to/elonmasai7/git-ofrenda-an-ofrenda-for-deleted-code-ehl</link>
      <guid>https://dev.to/elonmasai7/git-ofrenda-an-ofrenda-for-deleted-code-ehl</guid>
      <description>&lt;p&gt;*# git-ofrenda: An Ofrenda for Deleted Code&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;GitHub Repository:&lt;/strong&gt; &lt;a href="https://github.com/elonmasai7/git-ofrenda" rel="noopener noreferrer"&gt;https://github.com/elonmasai7/git-ofrenda&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Run this in any repository that is a few years old:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git log &lt;span class="nt"&gt;--diff-filter&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;D &lt;span class="nt"&gt;--name-only&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Every path it prints is a file someone wrote, fixed late at night, and eventually deleted. Git did not forget any of them. It still has who wrote each one, how many times it was touched, and the one-line commit message that ended it.&lt;/p&gt;

&lt;p&gt;That felt like the right ghost for this week's theme, so I built something to give them a proper send-off.&lt;/p&gt;

&lt;h2&gt;
  
  
  What I Built
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;git-ofrenda&lt;/strong&gt; is a command-line tool that finds the files a repository has lost and builds an ofrenda for them.&lt;/p&gt;

&lt;p&gt;For each deleted file, it works out when it was created, when it was deleted, who worked on it, who removed it and why, and what its last contents were. Then, a model running on your own machine writes the file some last words and a &lt;em&gt;calavera literaria&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;There are five commands:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;build&lt;/code&gt; generates the ofrenda as a self-contained HTML page, Markdown document, or JSON file.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;seance&lt;/code&gt; serves the page locally and lets you chat with individual files using their final contents and Git history.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;scan&lt;/code&gt; lists deleted files without requiring a model.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;exhume&lt;/code&gt; restores the last contents of deleted files, byte for byte, into a directory.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;doctor&lt;/code&gt; checks whether Git and the model server are configured correctly.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  How I Read the Theme
&lt;/h2&gt;

&lt;p&gt;An ofrenda is specific. It is the photograph, the favourite food, the marigolds, and a candle for each person. Those details make it an act of remembrance rather than a generic memorial.&lt;/p&gt;

&lt;p&gt;A &lt;em&gt;calavera literaria&lt;/em&gt; is an affectionate, teasing epitaph in verse associated with the Day of the Dead tradition. I borrowed the shape of these traditions for a programmer's joke, trying to keep the tone fond rather than mocking.&lt;/p&gt;

&lt;p&gt;I wanted the verses to know things.&lt;/p&gt;

&lt;p&gt;Not just, "Here lies a file. Rest in peace," but a verse about a file that spoke FTP to a partner's server for four years, only to be ended by a commit titled:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;remove ftp, partner moved to S3
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That is why the model receives the file's actual final contents and its Git history. The tool also extracts concrete details, such as function names, imports, and header comments, for its no-model fallback.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why Open Models Matter Here
&lt;/h2&gt;

&lt;p&gt;Deleted code is precisely the kind of code you may not want to upload anywhere. It can contain old credentials, internal hostnames, deprecated integrations, and embarrassing workarounds.&lt;/p&gt;

&lt;p&gt;Building an ofrenda with a hosted model could mean sending a repository's history to a third party. With an open-weight model, the entire pipeline can stay between Git and a server running on localhost, even without an internet connection.&lt;/p&gt;

&lt;p&gt;The design also supports multiple backends, verse caching, and operation without a model. The goal is to keep the project private, flexible, and independent of a single provider.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Moment It Landed
&lt;/h2&gt;

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

&lt;h2&gt;
  
  
  Things That Went Wrong
&lt;/h2&gt;

&lt;h3&gt;
  
  
  The Fallback Was Making Things Up
&lt;/h3&gt;

&lt;p&gt;The first template-generated verses sometimes treated filenames or meaningless comments as important parts of a file's history. Reviewing the output exposed the problem. The templates now mention functions only when they exist and quote header comments only when they contain enough meaningful information. I also added a regression test.&lt;/p&gt;

&lt;h3&gt;
  
  
  A Git Flag Failed Only on Large Repositories
&lt;/h3&gt;

&lt;p&gt;The pre-ranking step used when many deleted files exist passed &lt;code&gt;--format=@@&lt;/code&gt;, which Git interpreted as a named format and rejected.&lt;/p&gt;

&lt;p&gt;The issue appeared only when the repository contained more than 60 deleted files. A test that deletes 70 files exposed the bug.&lt;/p&gt;

&lt;h3&gt;
  
  
  Renames Can Misrepresent a File's History
&lt;/h3&gt;

&lt;p&gt;A file renamed in 2020 and deleted in 2024 can appear to have been created in 2020, even if its history began much earlier.&lt;/p&gt;

&lt;p&gt;Using &lt;code&gt;git log --follow&lt;/code&gt; helps recover its actual age. The command &lt;code&gt;--diff-filter=D -M&lt;/code&gt; also helps distinguish deleted files from files that were simply renamed.&lt;/p&gt;

&lt;h2&gt;
  
  
  How It Works
&lt;/h2&gt;

&lt;p&gt;The project separates repository analysis, verse generation, and presentation into distinct components.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;gitscan&lt;/code&gt;:&lt;/strong&gt; Finds deleted files, examines their history, and recovers their final contents from Git.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;poet&lt;/code&gt;:&lt;/strong&gt; Generates verses by checking the cache, querying the configured model, retrying once if generation fails, and falling back to templates when necessary.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;render&lt;/code&gt; and &lt;code&gt;server&lt;/code&gt;:&lt;/strong&gt; Present the ofrenda as a document or serve it through the local séance interface.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Every verse identifies its source, whether &lt;code&gt;template&lt;/code&gt; or the model's name. The page header also reports how many verses were model-generated.&lt;/p&gt;

&lt;p&gt;The séance server listens on &lt;code&gt;127.0.0.1&lt;/code&gt;, rejects foreign &lt;code&gt;Host&lt;/code&gt; headers, and requires a custom header for POST requests. Repository contents and model-generated output are HTML-escaped before being inserted into the page.&lt;/p&gt;

&lt;h2&gt;
  
  
  Tests
&lt;/h2&gt;

&lt;p&gt;The project includes 45 tests covering repository analysis, file history, model integration, and HTTP behaviour.&lt;/p&gt;

&lt;p&gt;The tests build real Git repositories to exercise deletions, renames, binary files, large numbers of deleted files, model server failures, malformed responses, and HTTP streaming.&lt;/p&gt;

&lt;p&gt;Mock Ollama and OpenAI-compatible servers verify that the client follows the expected protocols. These tests provide confidence in the tool's behaviour, but they do not measure poetry quality.&lt;/p&gt;

&lt;h2&gt;
  
  
  Try It
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Repository:&lt;/strong&gt; &lt;a href="https://github.com/elonmasai7/git-ofrenda" rel="noopener noreferrer"&gt;github.com/elonmasai7/git-ofrenda&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Clone and install the project:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git clone https://github.com/elonmasai7/git-ofrenda.git
&lt;span class="nb"&gt;cd &lt;/span&gt;git-ofrenda
pip &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nb"&gt;.&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you want to use Ollama, install and start it first, then pull the model:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;ollama pull gemma3
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Check your environment:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git-ofrenda doctor
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Generate an ofrenda or start a local séance:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git-ofrenda build
git-ofrenda seance
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Terminal Session
&lt;/h3&gt;

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

&lt;h3&gt;
  
  
  Chatting With a File
&lt;/h3&gt;

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

&lt;h2&gt;
  
  
  Limitations and What's Next
&lt;/h2&gt;

&lt;p&gt;Heavily rewritten files can still look like a death followed by a birth. Only the first 2,500 characters of a file are sent to the model, and smaller models sometimes ignore the requested verse format, causing the tool to fall back to a template.&lt;/p&gt;

&lt;p&gt;The next feature I would like to build is a GitHub Action that publishes an ofrenda each year for the files deleted during that year.&lt;/p&gt;

&lt;p&gt;It would turn an ordinary maintenance history into a small annual ritual: a chance to revisit the code that once mattered, understand why it disappeared, and remember the work that went into building it.&lt;/p&gt;

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

&lt;p&gt;Git is excellent at remembering what happened to a codebase. It records changes, authors, and commit messages with remarkable persistence.&lt;/p&gt;

&lt;p&gt;But it does not usually encourage us to stop and reflect on what those changes mean.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;git-ofrenda&lt;/strong&gt; is my attempt to add that missing moment of reflection. It takes something as ordinary as a deleted file and turns its history into a small memorial, using local models to keep the process private and accessible.&lt;/p&gt;

&lt;p&gt;Sometimes, even deleted code deserves a proper goodbye.&lt;/p&gt;




&lt;p&gt;&lt;strong&gt;Explore the project on GitHub:&lt;/strong&gt; &lt;a href="https://github.com/elonmasai7/git-ofrenda" rel="noopener noreferrer"&gt;https://github.com/elonmasai7/git-ofrenda&lt;/a&gt;&lt;/p&gt;

</description>
      <category>devchallenge</category>
      <category>hf26challenge</category>
    </item>
    <item>
      <title>SlothWatch is an AI agent whose best output is silence.</title>
      <dc:creator>Elon masai</dc:creator>
      <pubDate>Sun, 25 Oct 2026 17:29:26 +0000</pubDate>
      <link>https://dev.to/elonmasai7/slothwatch-is-an-ai-agent-whose-best-output-is-silence-cf3</link>
      <guid>https://dev.to/elonmasai7/slothwatch-is-an-ai-agent-whose-best-output-is-silence-cf3</guid>
      <description>&lt;p&gt;&lt;em&gt;This is a submission for the &lt;a href="https://dev.to/challenges/hacktoberfest-week3-2026-10-19"&gt;Hacktoberfest Open-Source AI Challenge Week 3: Slow and Steady&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  What I Built
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;SlothWatch is an AI agent whose best output is silence.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Every "lazy" AI tool I've seen does the same thing: it summarizes more stuff so you can read it. That isn't laziness, it's a new inbox. A sloth doesn't summarize the forest. A sloth stays asleep until something actually matters.&lt;/p&gt;

&lt;p&gt;So SlothWatch watches the boring numbers in your life (bank CSV exports, bills, subscriptions) and does nothing unless something is wrong. Most nights, it says this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Nothing needs you. Go back to sleep. (45 rows checked, 0 surprises. Receipt #1)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


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

&lt;p&gt;When something &lt;em&gt;is&lt;/em&gt; wrong, it wakes up, tells you in two plain sentences, and drafts the dispute message for you. It never sends anything. You approve, ignore, or snooze.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The effort it saves:&lt;/strong&gt; I never have to open a bank statement to hunt for the subscription that quietly went up 40%, the grocery store that charged me twice, or the electricity bill that doubled. The agent reads every row so I read none.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Who gets to be lazier:&lt;/strong&gt; anyone who dreads "I should really check my statements." That's most of us.&lt;/p&gt;
&lt;h2&gt;
  
  
  Demo
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Live demo: &lt;a href="https://slothwatch-demo.onrender.com/" rel="noopener noreferrer"&gt;https://slothwatch-demo.onrender.com/&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;It's hosted on Render and runs on a fully synthetic person (seeded, so every run is identical), so no real financial data is ever involved. The hosted dashboard boots into a clean month, so the sloth starts asleep. If the page takes a moment to load, the free instance is waking up. That seemed appropriate.&lt;/p&gt;

&lt;p&gt;To watch the agent catch things, run the scenarios locally. Here is the "everything goes wrong" month: a streaming plan up 40%, a duplicate grocery charge, an electricity spike, and an insurance premium creeping up 3% a month.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fqyh3gjgv6sh6ehrmz20d.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fqyh3gjgv6sh6ehrmz20d.png" alt="Everything goes wrong: 47 rows checked, the model woke 4 times" width="800" height="406"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;And here is a sloth's diary of the duplicate-charge month, one line per day:&lt;/p&gt;

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


&lt;div class="ltag-github-readme-tag"&gt;
  &lt;div class="readme-overview"&gt;
    &lt;h2&gt;
      &lt;img src="https://assets.dev.to/assets/github-logo-5a155e1f9a670af7944dd5e12375bc76ed542ea80224905ecaf878b9157cdefc.svg" alt="GitHub logo"&gt;
      &lt;a href="https://github.com/elonmasai7" rel="noopener noreferrer"&gt;
        elonmasai7
      &lt;/a&gt; / &lt;a href="https://github.com/elonmasai7/slothwatch" rel="noopener noreferrer"&gt;
        slothwatch
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
       fully local agent that watches boring personal numbers (bank CSV exports, utility bills, subscriptions) and does nothing unless something is off. Success state is silence: "Nothing needs you. Go back to sleep."
    &lt;/h3&gt;
  &lt;/div&gt;
  &lt;div class="ltag-github-body"&gt;
    
&lt;div id="readme" class="md"&gt;&lt;div class="markdown-heading"&gt;
&lt;h1 class="heading-element"&gt;SlothWatch 🦥  the agent whose best output is silence&lt;/h1&gt;
&lt;/div&gt;

&lt;p&gt;A local agent that watches boring money numbers (bank CSVs) and stays quiet unless something is wrong
&lt;strong&gt;"Nothing needs you. Go back to sleep. (45 rows checked, 0 surprises. Receipt #1)"&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Two apps, one core:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;SlothWatch (real)&lt;/strong&gt;: your CSVs, your schedule. State in &lt;code&gt;.slothwatch/&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;SlothWatch Demo&lt;/strong&gt;: seeded synthetic life, six scenario packs, fast-forward sloth diary, guided tour, 12-week simulation. State in &lt;code&gt;.slothwatch-demo/&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;Screenshots&lt;/h2&gt;
&lt;/div&gt;
&lt;p&gt;All captured from real runs of this repo (synthetic demo data). Regenerate any of them with the command shown.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;1. A clean month: silence is the product&lt;/strong&gt; (&lt;code&gt;slothwatch-demo run clean-month&lt;/code&gt;)&lt;/p&gt;
&lt;p&gt;&lt;a rel="noopener noreferrer" href="https://github.com/elonmasai7/slothwatch/docs/screenshots/01-silence.png"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fraw.githubusercontent.com%2Felonmasai7%2Fslothwatch%2FHEAD%2Fdocs%2Fscreenshots%2F01-silence.png" alt="A clean month"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;2. Everything goes wrong: the ladder wakes the model only 4 times out of 47 rows&lt;/strong&gt; (&lt;code&gt;slothwatch-demo run everything-wrong&lt;/code&gt;)&lt;/p&gt;
&lt;p&gt;&lt;a rel="noopener noreferrer" href="https://github.com/elonmasai7/slothwatch/docs/screenshots/02-ladder.png"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fraw.githubusercontent.com%2Felonmasai7%2Fslothwatch%2FHEAD%2Fdocs%2Fscreenshots%2F02-ladder.png" alt="The ladder in action"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;3. A sloth's diary: 30 days, one line per day&lt;/strong&gt; (&lt;code&gt;slothwatch-demo fast duplicate-charge&lt;/code&gt;)&lt;/p&gt;
&lt;p&gt;&lt;a rel="noopener noreferrer" href="https://github.com/elonmasai7/slothwatch/docs/screenshots/03-diary.png"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fraw.githubusercontent.com%2Felonmasai7%2Fslothwatch%2FHEAD%2Fdocs%2Fscreenshots%2F03-diary.png" alt="Sloth diary"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;4. Silence with a receipt: spot-check&lt;/strong&gt;…&lt;/p&gt;&lt;/div&gt;
  &lt;/div&gt;
  &lt;div class="gh-btn-container"&gt;&lt;a class="gh-btn" href="https://github.com/elonmasai7/slothwatch" rel="noopener noreferrer"&gt;View on GitHub&lt;/a&gt;&lt;/div&gt;
&lt;/div&gt;


&lt;p&gt;About 2,650 lines of Python and 28 tests. The core uses &lt;strong&gt;only the standard library&lt;/strong&gt;, so you can clone it and run the demo with nothing installed:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;python3 &lt;span class="nt"&gt;-m&lt;/span&gt; slothwatch.demo.cli run clean-month
python3 &lt;span class="nt"&gt;-m&lt;/span&gt; slothwatch.demo.cli run everything-wrong
python3 &lt;span class="nt"&gt;-m&lt;/span&gt; slothwatch.demo.cli tour
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  How I Built It
&lt;/h2&gt;

&lt;p&gt;The central idea: laziness should be the &lt;em&gt;architecture&lt;/em&gt;, not just the theme. I call it the &lt;strong&gt;Sloth Ladder&lt;/strong&gt;. Every layer exists to avoid waking the next one.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Rung&lt;/th&gt;
&lt;th&gt;What it does&lt;/th&gt;
&lt;th&gt;Open piece&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;0&lt;/td&gt;
&lt;td&gt;Plain rules: exact duplicates, same-as-last-month, ignore-list. Settles most rows for free.&lt;/td&gt;
&lt;td&gt;none needed&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;Forecasts what each recurring bill &lt;em&gt;should&lt;/em&gt; be, with a prediction interval. Inside the interval = boring.&lt;/td&gt;
&lt;td&gt;
&lt;strong&gt;TabPFN&lt;/strong&gt;, run locally&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;1.5&lt;/td&gt;
&lt;td&gt;"Does this person care?" Learns from your approve/ignore decisions and hushes things you always dismiss.&lt;/td&gt;
&lt;td&gt;
&lt;strong&gt;TabPFN&lt;/strong&gt; classifier, in-context&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;td&gt;Wakes only for real surprises. Writes a two-sentence verdict, a severity, and a draft message as strict JSON.&lt;/td&gt;
&lt;td&gt;
&lt;strong&gt;Gemma&lt;/strong&gt; via Ollama&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;3&lt;/td&gt;
&lt;td&gt;You. Pinged only for severity "act".&lt;/td&gt;
&lt;td&gt;you&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;A few decisions that mattered:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;1. TabPFN is the "is this surprising?" gate.&lt;/strong&gt; It's a tabular foundation model that learns in context, so there's no training pipeline to build or babysit. A few months of a bill's history goes in; a forecast with a prediction interval comes out. That is the laziest possible way to get a defensible "normal."&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2. Gemma only sees the flagged row.&lt;/strong&gt; The prompt contains one charge and its forecast context, never the whole statement. Output is schema-validated JSON with one retry and a clearly labelled templated fallback, so the nightly run never breaks if the model is down.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;3. Silence has to be verifiable.&lt;/strong&gt; An agent that says nothing looks exactly like a broken agent. So every run, quiet or not, writes a &lt;strong&gt;Silence Receipt&lt;/strong&gt;: rows checked, which rung settled each one, and why. Receipts are hash-chained, &lt;code&gt;slothwatch verify&lt;/code&gt; recomputes the chain, and &lt;code&gt;slothwatch receipt --sample 3&lt;/code&gt; shows three random rows it left alone with the interval that cleared them. A weekly &lt;strong&gt;canary&lt;/strong&gt; plants a fake anomaly in a copy of the data and checks that the ladder catches it.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fcn6ecg9wdv3dc94jpesx.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fcn6ecg9wdv3dc94jpesx.png" alt="Three rows it left alone, with the interval that cleared each, and a verified chain" width="799" height="233"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;4. Temporal makes it nap durably.&lt;/strong&gt; The nightly run is a Temporal workflow that retries flaky steps, then &lt;em&gt;sleeps up to seven days&lt;/em&gt; waiting on a signal for your decision. The pipeline is idempotent per date window, so a worker crash can't produce a second alert.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;5. Every rung is a traced span&lt;/strong&gt; (Sentry Agent Tracing, with a local JSONL fallback) recording latency, tokens, whether it woke, and cost. Local inference shows $0.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;6. The demo is deployable on Render.&lt;/strong&gt; A &lt;code&gt;render.yaml&lt;/code&gt; Blueprint in the repo deploys only the synthetic dashboard. It is deliberately not meant for real bank data: the real app stays on your own machine.&lt;/p&gt;

&lt;p&gt;Under the hood it's deliberately plain: a pure &lt;code&gt;run_ladder()&lt;/code&gt; function, SQLite, and a dashboard built on &lt;code&gt;http.server&lt;/code&gt; with one HTML file and no CDNs, so it works with the wifi off.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why Does Open Innovation Matter?
&lt;/h2&gt;

&lt;p&gt;Because this tool reads the most sensitive file most people own, and &lt;strong&gt;I can prove it never leaves my machine.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;code&gt;slothwatch privacy-check&lt;/code&gt; runs the entire pipeline with every non-local network connection and DNS lookup blocked and recorded. It fails if anything tries to phone home. It's also a unit test.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fjrsaj9j7nxweji4pvnpd.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fjrsaj9j7nxweji4pvnpd.png" alt="The pipeline runs with all external network access blocked, and 28 tests pass" width="799" height="246"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;That is only possible because the models are open-weight and run locally. With a closed API, the honest version of this product means uploading your bank statements to a third party and paying per token on every row. Open models gave me things a closed API wouldn't:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Privacy you can test&lt;/strong&gt;, not just a policy you have to trust.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;$0 per run&lt;/strong&gt;, which is what makes "check every row, every night" sane.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Control over behavior.&lt;/strong&gt; Prompts are versioned text files, rules live in a TOML file, the model is one config key, and the Rung 2 model can be swapped or fine-tuned.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;It works offline.&lt;/strong&gt; The sloth doesn't need wifi.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This is also why the hosted demo uses synthetic data only. The public link shows the idea, and your real statements never need to touch a server you don't control.&lt;/p&gt;

&lt;h2&gt;
  
  
  My Agent Session
&lt;/h2&gt;

&lt;p&gt;⟦ EMBED agent_session ⟧&lt;/p&gt;

&lt;h2&gt;
  
  
  The Lazy Payoff
&lt;/h2&gt;

&lt;p&gt;The point of the ladder is how rarely the expensive layers run. I benchmarked it against the naive "send every row to the LLM" approach across six scenarios (one clean month plus five kinds of problem):&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Frrlun6at9at0sij7c57w.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Frrlun6at9at0sij7c57w.png" alt="Model wake-ups per scenario: ladder versus send-every-row" width="800" height="462"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;8 model wake-ups&lt;/strong&gt; with the ladder versus &lt;strong&gt;274&lt;/strong&gt; for send-every-row: 97% fewer.&lt;/li&gt;
&lt;li&gt;On a typical bad month: &lt;strong&gt;47 rows checked, 42 settled by rules, 1 by forecast, and the model woke 4 times.&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Every planted anomaly was caught, with zero false positives (on synthetic data, so real statements will be messier).&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I also simulated twelve weeks with a persona that has consistent tastes (always approves duplicate charges, ignores small utility wobbles), once with learning off and once on:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fobfjw2bz1v5wirvlhmw5.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fobfjw2bz1v5wirvlhmw5.png" alt="The Laziness Curve: wake-ups per week with learning on versus off" width="800" height="462"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I want to be straight about this one. The effect is &lt;strong&gt;real but modest&lt;/strong&gt;: 56 wake-ups fell to 47 (16% fewer), and in a 26-week run 106 fell to 90. The two curves are identical until week 6, because the agent needs 15 labelled decisions before it is allowed to hush anything. Safety rails stop it from ever suppressing a large charge, and in both runs it still caught all 19 true anomalies. I'd rather show you a small honest curve than a dramatic invented one.&lt;/p&gt;

&lt;p&gt;⟦ One sentence about your real use this week, or delete this line ⟧&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What isn't proven yet:&lt;/strong&gt; the benchmark ran with Gemma's templated fallback (labelled "offline" in the report), so its token counts are &lt;em&gt;estimated&lt;/em&gt;. ⟦ After running with Ollama: "With &lt;code&gt;gemma3:4b&lt;/code&gt; live, a wake-up took ___ ms and ___ tokens." ⟧ The Tinker fine-tuning harness (dataset plus evaluation) is built and tested, but I'm not claiming a tuned-versus-stock improvement I didn't measure.&lt;/p&gt;

&lt;h2&gt;
  
  
  Prize Categories
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Best Use of Render:&lt;/strong&gt; the synthetic demo dashboard is deployed on Render from a &lt;code&gt;render.yaml&lt;/code&gt; Blueprint: &lt;a href="https://slothwatch-demo.onrender.com/" rel="noopener noreferrer"&gt;https://slothwatch-demo.onrender.com/&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Best Use of TabPFN:&lt;/strong&gt; forecast intervals (Rung 1) and the in-context "does this person care?" classifier (Rung 1.5), inside a wider prediction agent.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Best Use of Gemma:&lt;/strong&gt; the Rung 2 explainer, running locally via Ollama, waking only for flagged rows.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Best Use of Temporal:&lt;/strong&gt; a durable nightly workflow that retries, sleeps on a signal, and is idempotent across crashes.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Best Use of Sentry Agent Tracing:&lt;/strong&gt; one span per rung with latency, tokens, wake/sleep, and cost.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Best Use of Entire:&lt;/strong&gt; agent sessions linked above.&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>devchallenge</category>
      <category>hf26challenge</category>
    </item>
  </channel>
</rss>
