<?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>Forem: Mason Delan</title>
    <description>The latest articles on Forem by Mason Delan (@masondelan).</description>
    <link>https://forem.com/masondelan</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.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3895217%2F43e15a74-e526-44b8-9efa-403e4549ac59.png</url>
      <title>Forem: Mason Delan</title>
      <link>https://forem.com/masondelan</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/masondelan"/>
    <language>en</language>
    <item>
      <title>A week and four releases later, this is still the framing I keep coming back to. The install friction the article describes (six manual steps) is what v0.3.4 collapsed to one command this weekend.

pip install selvedge</title>
      <dc:creator>Mason Delan</dc:creator>
      <pubDate>Fri, 01 May 2026 01:33:56 +0000</pubDate>
      <link>https://forem.com/masondelan/a-week-and-four-releases-later-this-is-still-the-framing-i-keep-coming-back-to-the-install-59mc</link>
      <guid>https://forem.com/masondelan/a-week-and-four-releases-later-this-is-still-the-framing-i-keep-coming-back-to-the-install-59mc</guid>
      <description>&lt;div class="ltag__link--embedded"&gt;
  &lt;div class="crayons-story "&gt;
  &lt;a href="https://dev.to/masondelan/the-silent-problem-with-ai-written-code-the-intent-evaporates-14c4" class="crayons-story__hidden-navigation-link"&gt;The silent problem with AI-written code: the intent evaporates&lt;/a&gt;


  &lt;div class="crayons-story__body crayons-story__body-full_post"&gt;
    &lt;div class="crayons-story__top"&gt;
      &lt;div class="crayons-story__meta"&gt;
        &lt;div class="crayons-story__author-pic"&gt;

          &lt;a href="/masondelan" class="crayons-avatar  crayons-avatar--l  "&gt;
            &lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3895217%2F43e15a74-e526-44b8-9efa-403e4549ac59.png" alt="masondelan profile" class="crayons-avatar__image" width="240" height="240"&gt;
          &lt;/a&gt;
        &lt;/div&gt;
        &lt;div&gt;
          &lt;div&gt;
            &lt;a href="/masondelan" class="crayons-story__secondary fw-medium m:hidden"&gt;
              Mason Delan
            &lt;/a&gt;
            &lt;div class="profile-preview-card relative mb-4 s:mb-0 fw-medium hidden m:inline-block"&gt;
              
                Mason Delan
                
              
              &lt;div id="story-author-preview-content-3543917" class="profile-preview-card__content crayons-dropdown branded-7 p-4 pt-0"&gt;
                &lt;div class="gap-4 grid"&gt;
                  &lt;div class="-mt-4"&gt;
                    &lt;a href="/masondelan" class="flex"&gt;
                      &lt;span class="crayons-avatar crayons-avatar--xl mr-2 shrink-0"&gt;
                        &lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3895217%2F43e15a74-e526-44b8-9efa-403e4549ac59.png" class="crayons-avatar__image" alt="" width="240" height="240"&gt;
                      &lt;/span&gt;
                      &lt;span class="crayons-link crayons-subtitle-2 mt-5"&gt;Mason Delan&lt;/span&gt;
                    &lt;/a&gt;
                  &lt;/div&gt;
                  &lt;div class="print-hidden"&gt;
                    
                      Follow
                    
                  &lt;/div&gt;
                  &lt;div class="author-preview-metadata-container"&gt;&lt;/div&gt;
                &lt;/div&gt;
              &lt;/div&gt;
            &lt;/div&gt;

          &lt;/div&gt;
          &lt;a href="https://dev.to/masondelan/the-silent-problem-with-ai-written-code-the-intent-evaporates-14c4" class="crayons-story__tertiary fs-xs"&gt;&lt;time&gt;Apr 24&lt;/time&gt;&lt;span class="time-ago-indicator-initial-placeholder"&gt;&lt;/span&gt;&lt;/a&gt;
        &lt;/div&gt;
      &lt;/div&gt;

    &lt;/div&gt;

    &lt;div class="crayons-story__indention"&gt;
      &lt;h2 class="crayons-story__title crayons-story__title-full_post"&gt;
        &lt;a href="https://dev.to/masondelan/the-silent-problem-with-ai-written-code-the-intent-evaporates-14c4" id="article-link-3543917"&gt;
          The silent problem with AI-written code: the intent evaporates
        &lt;/a&gt;
      &lt;/h2&gt;
        &lt;div class="crayons-story__tags"&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/ai"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;ai&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/claudecode"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;claudecode&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/mcp"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;mcp&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/opensource"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;opensource&lt;/a&gt;
        &lt;/div&gt;
      &lt;div class="crayons-story__bottom"&gt;
        &lt;div class="crayons-story__details"&gt;
          &lt;a href="https://dev.to/masondelan/the-silent-problem-with-ai-written-code-the-intent-evaporates-14c4" class="crayons-btn crayons-btn--s crayons-btn--ghost crayons-btn--icon-left"&gt;
            &lt;div class="multiple_reactions_aggregate"&gt;
              &lt;span class="multiple_reactions_icons_container"&gt;
                  &lt;span class="crayons_icon_container"&gt;
                    &lt;img src="https://assets.dev.to/assets/sparkle-heart-5f9bee3767e18deb1bb725290cb151c25234768a0e9a2bd39370c382d02920cf.svg" width="24" height="24"&gt;
                  &lt;/span&gt;
              &lt;/span&gt;
              &lt;span class="aggregate_reactions_counter"&gt;3&lt;span class="hidden s:inline"&gt; reactions&lt;/span&gt;&lt;/span&gt;
            &lt;/div&gt;
          &lt;/a&gt;
            &lt;a href="https://dev.to/masondelan/the-silent-problem-with-ai-written-code-the-intent-evaporates-14c4#comments" class="crayons-btn crayons-btn--s crayons-btn--ghost crayons-btn--icon-left flex items-center"&gt;
              Comments


              1&lt;span class="hidden s:inline"&gt; comment&lt;/span&gt;
            &lt;/a&gt;
        &lt;/div&gt;
        &lt;div class="crayons-story__save"&gt;
          &lt;small class="crayons-story__tertiary fs-xs mr-2"&gt;
            4 min read
          &lt;/small&gt;
            
              &lt;span class="bm-initial"&gt;
                

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

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

&lt;/div&gt;


</description>
      <category>ai</category>
      <category>automation</category>
      <category>python</category>
      <category>showdev</category>
    </item>
    <item>
      <title>I rebuilt the install for my "git blame for AI" tool — six steps became one</title>
      <dc:creator>Mason Delan</dc:creator>
      <pubDate>Fri, 01 May 2026 01:27:47 +0000</pubDate>
      <link>https://forem.com/masondelan/i-rebuilt-the-install-for-my-git-blame-for-ai-tool-six-steps-became-one-2eob</link>
      <guid>https://forem.com/masondelan/i-rebuilt-the-install-for-my-git-blame-for-ai-tool-six-steps-became-one-2eob</guid>
      <description>&lt;p&gt;A week ago I shipped &lt;a href="https://github.com/masondelan/selvedge" rel="noopener noreferrer"&gt;Selvedge&lt;/a&gt;, an MCP server that captures &lt;em&gt;why&lt;/em&gt; AI agents change code. The first dev.to post laid out the problem; this one is what's happened since.&lt;/p&gt;

&lt;p&gt;Quick context if you missed the first one: AI agents write code with full intent in the moment, and then the session ends and the intent is gone. Selvedge captures that intent live, by the agent, while it's still in context. Then six months later you can ask &lt;code&gt;selvedge blame users.email&lt;/code&gt; and get an actual sentence back about why the column exists.&lt;/p&gt;

&lt;p&gt;The original launch did fine. A few hundred installs, a handful of stars, one post on each of dev.to and HN that converted better than I expected. Nothing dramatic. But the shape of where people dropped off was instructive, and that's what the v0.3.4 release I shipped this weekend is mostly about.&lt;/p&gt;

&lt;h2&gt;
  
  
  The install was the bottleneck and I was kidding myself
&lt;/h2&gt;

&lt;p&gt;I knew the install wasn't great. The first version of the README walked you through six things:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;code&gt;pip install selvedge&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;cd your-project &amp;amp;&amp;amp; selvedge init&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Open &lt;code&gt;~/.claude/config.json&lt;/code&gt; and add an &lt;code&gt;mcpServers.selvedge&lt;/code&gt; block. Hope you got the JSON right.&lt;/li&gt;
&lt;li&gt;Open your project's &lt;code&gt;CLAUDE.md&lt;/code&gt; (or create one). Paste in the system prompt that tells the agent to call &lt;code&gt;log_change&lt;/code&gt; whenever it touches a column, function, env var, or dependency.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;selvedge install-hook&lt;/code&gt; so post-commit can link events to commits.&lt;/li&gt;
&lt;li&gt;Restart Claude Code, because the MCP config doesn't hot-reload.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Four flips between the README and your editor. One of those steps — number three — is "edit a JSON file by hand," which kills curiosity in about eight seconds. And number five, the post-commit hook, silently failed on macOS when you committed through a GUI client like Tower or GitKraken, because git launches with a stripped PATH and &lt;code&gt;selvedge&lt;/code&gt; isn't on it. I wrote &lt;code&gt;selvedge doctor&lt;/code&gt; in v0.3.2 specifically because of that bug. The bug existed because the install didn't surface that the hook was even there to fail.&lt;/p&gt;

&lt;p&gt;What actually happened in the install metrics is roughly what you'd expect. People &lt;code&gt;pip install&lt;/code&gt;-ed. Some ran &lt;code&gt;selvedge init&lt;/code&gt;. A much smaller fraction ever made it to the point where &lt;code&gt;tool_calls&lt;/code&gt; started arriving at the server, which is the only thing I actually care about. The JSON edit and the CLAUDE.md edit are where the cliff is.&lt;/p&gt;

&lt;p&gt;Anyway. v0.3.4 collapses all of that to one command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;pip &lt;span class="nb"&gt;install &lt;/span&gt;selvedge
&lt;span class="nb"&gt;cd &lt;/span&gt;your-project
selvedge setup
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The wizard reads &lt;code&gt;~/.claude/config.json&lt;/code&gt;, &lt;code&gt;~/.cursor/mcp.json&lt;/code&gt;, and looks for &lt;code&gt;.github/copilot-instructions.md&lt;/code&gt; — whichever of those you actually have, it configures. It writes the MCP entry. It drops the system-prompt block into your &lt;code&gt;CLAUDE.md&lt;/code&gt; or &lt;code&gt;.cursorrules&lt;/code&gt;, sentinel-bracketed so the next time I update the recommended block you can re-run &lt;code&gt;selvedge prompt --install&lt;/code&gt; and it patches in place without disturbing the rest of your file. It runs &lt;code&gt;selvedge init&lt;/code&gt;. It installs the hook. It writes a &lt;code&gt;.bak&lt;/code&gt; next to every file it touches before any change reaches disk, so if it makes a wrong call you can revert.&lt;/p&gt;

&lt;p&gt;Re-running on an already-set-up project is a no-op. For people running it in CI or &lt;code&gt;devcontainer.json&lt;/code&gt;'s &lt;code&gt;postCreateCommand&lt;/code&gt;: &lt;code&gt;selvedge setup --non-interactive --yes&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;That's it. The "interesting" parts of Selvedge — the live reasoning capture, the entity-level history, the changesets — are useless if nobody gets past the install. Six manual steps was burning everyone who would have otherwise tried it. One command isn't.&lt;/p&gt;

&lt;h2&gt;
  
  
  On not being alone in the category anymore
&lt;/h2&gt;

&lt;p&gt;Other thing that changed since the launch post: the "git blame for AI" space has gotten crowded fast. AgentDiff, Origin, Git AI, BlamePrompt — all real tools, all active, several of them backed by named teams. When I posted the first article a week ago I had basically one direct competitor I knew about. Now I have four or five.&lt;/p&gt;

&lt;p&gt;That's actually fine. It means the problem is real enough that more than one person decided to work on it. But it does mean I should be specific about what's different, because if you read every tool's README in isolation you'd reasonably conclude they're all doing the same thing.&lt;/p&gt;

&lt;p&gt;The thing that's actually different is &lt;em&gt;when&lt;/em&gt; the reasoning gets captured.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;/th&gt;
&lt;th&gt;Reasoning source&lt;/th&gt;
&lt;th&gt;Granularity&lt;/th&gt;
&lt;th&gt;Mechanism&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Selvedge&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Captured live, by the agent in the same context that produced the change&lt;/td&gt;
&lt;td&gt;Entity (DB column, table, env var, dep, API route, function)&lt;/td&gt;
&lt;td&gt;MCP server — agent calls it as work happens&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;AgentDiff&lt;/td&gt;
&lt;td&gt;Inferred post-hoc by Claude Haiku from the diff at session end&lt;/td&gt;
&lt;td&gt;Line&lt;/td&gt;
&lt;td&gt;Git pre/post-commit hook&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Origin&lt;/td&gt;
&lt;td&gt;Captured at commit time&lt;/td&gt;
&lt;td&gt;Line&lt;/td&gt;
&lt;td&gt;Git hook&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Git AI&lt;/td&gt;
&lt;td&gt;Attribution metadata&lt;/td&gt;
&lt;td&gt;Line&lt;/td&gt;
&lt;td&gt;Git hook + Agent Trace alliance&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;BlamePrompt&lt;/td&gt;
&lt;td&gt;Prompt-only&lt;/td&gt;
&lt;td&gt;Line&lt;/td&gt;
&lt;td&gt;Git hook&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Most of these tools wait until commit time and then ask a second LLM to look at the diff and explain what changed. That's a reasonable approach and the output looks fine on first read. But it's not the actual reasoning the agent had — the agent had the prompt, the conversation history, the user's actual ask, and a model's interpretation of all of it. The post-hoc explainer doesn't have any of that. It has the diff. So it generates something plausible.&lt;/p&gt;

&lt;p&gt;Plausible isn't always right. If you migrated from &lt;code&gt;INTEGER cents&lt;/code&gt; to &lt;code&gt;DECIMAL(10,2)&lt;/code&gt; because a user reported rounding errors on international transactions, that's the actual reason. If a second LLM looks at the diff months later, it'll write something like "improved precision for monetary values" — true in a generic sense, useless when you're trying to figure out which currencies you should regression-test next time.&lt;/p&gt;

&lt;p&gt;Selvedge's reasoning is whatever the agent that made the change wrote. It comes from the same context window that produced the change. There's no second model and no inference. And because it's whatever the agent had, an empty &lt;code&gt;reasoning&lt;/code&gt; field is itself useful information — it means the agent didn't have explicit intent for that change, which is honestly the case you want to know about most.&lt;/p&gt;

&lt;h2&gt;
  
  
  Entity attribution, briefly
&lt;/h2&gt;

&lt;p&gt;The other thing that's a bit different: most tools attribute &lt;em&gt;lines&lt;/em&gt;. Selvedge attributes &lt;em&gt;things&lt;/em&gt;. When you investigate something in your codebase you don't search "lines 40 through 48 of users.py", you search "users.email" or "STRIPE_SECRET_KEY" or "/api/v1/checkout". So that's what Selvedge stores:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;users.email           DB column
users                 DB table
src/auth.py::login    Function in a file
api/v1/users          API route
deps/stripe           Dependency
env/STRIPE_SECRET_KEY Environment variable
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;selvedge diff users&lt;/code&gt; returns events for &lt;code&gt;users&lt;/code&gt;, &lt;code&gt;users.email&lt;/code&gt;, and anything else under &lt;code&gt;users.&lt;/code&gt;. Same for any prefix.&lt;/p&gt;

&lt;p&gt;I went back and forth on whether to also attribute lines (more granular, more like what the other tools do) and decided not to. Lines drift. Renames break attribution. Refactoring a function into three files invalidates everything that referenced the original location. Entities are sticky in a way that lines aren't.&lt;/p&gt;

&lt;h2&gt;
  
  
  Changesets
&lt;/h2&gt;

&lt;p&gt;The other thing in Selvedge I haven't seen anywhere else is changesets — a slug you can attach to any event, so later you can pull every event for a feature back, regardless of how many entities it touched or how many PRs it spanned.&lt;/p&gt;

&lt;p&gt;The example I keep coming back to is Stripe billing. A real billing rollout in a real codebase touches new columns on &lt;code&gt;users&lt;/code&gt;, two new env vars, three new API routes, a new dependency, four functions across the codebase, and lands as eight smaller PRs over a month because nobody wants to review one mega-diff.&lt;/p&gt;

&lt;p&gt;Six months later somebody has to audit which lines of code touch payment data — for compliance, for an incident, for a refactor. &lt;code&gt;git log&lt;/code&gt; is useless for this. Each PR is generic ("update billing", "wire webhook", "fix typo in migration") and the cross-cutting nature is just gone.&lt;/p&gt;

&lt;p&gt;If every event in that work was tagged &lt;code&gt;changeset:add-stripe-billing&lt;/code&gt;, you run &lt;code&gt;selvedge changeset add-stripe-billing&lt;/code&gt; and get every event from every entity that was part of it, with the agent's reasoning on each. It's the rollup view. Nobody else stores it as far as I can tell, because it requires capturing reasoning at the per-change level, which only really works if you're capturing live.&lt;/p&gt;

&lt;h2&gt;
  
  
  Agent Trace
&lt;/h2&gt;

&lt;p&gt;A few people DM'd me about &lt;a href="https://github.com/cursor/agent-trace" rel="noopener noreferrer"&gt;Agent Trace&lt;/a&gt; after the first article. Cursor and Cognition put out an RFC in January for an open standard for AI code attribution traces. JSON records, file/line granularity, deliberately storage-agnostic. Cloudflare, Vercel, Google Jules, Amp, OpenCode, and git-ai are all signed on.&lt;/p&gt;

&lt;p&gt;Selvedge isn't competing with that. It's a producer for it. Agent Trace is the wire format; Selvedge is one way to populate that wire format (live, from the agent, at the moment the change is made). The export design is at &lt;a href="https://github.com/masondelan/selvedge/blob/main/docs/agent-trace-interop.md" rel="noopener noreferrer"&gt;&lt;code&gt;docs/agent-trace-interop.md&lt;/code&gt;&lt;/a&gt;. I'll ship the actual &lt;code&gt;selvedge export --format agent-trace&lt;/code&gt; flag in v0.3.5 or v0.4.&lt;/p&gt;

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



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;pip &lt;span class="nb"&gt;install &lt;/span&gt;selvedge
&lt;span class="nb"&gt;cd &lt;/span&gt;your-project
selvedge setup
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then start an agent session in that directory, change something non-trivial, and in a separate terminal:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;selvedge watch
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You should see events stream in as the agent calls &lt;code&gt;log_change&lt;/code&gt;. Once a few have landed:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;selvedge blame &amp;lt;whatever_you_just_changed&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The reasoning was captured live. That's the whole product.&lt;/p&gt;

&lt;p&gt;If nothing arrives in &lt;code&gt;selvedge watch&lt;/code&gt;, run &lt;code&gt;selvedge doctor&lt;/code&gt;. It'll tell you which step is silently broken. (There are still ways for it to be silently broken. I'm working on them.)&lt;/p&gt;

&lt;h2&gt;
  
  
  What's next, and what I want feedback on
&lt;/h2&gt;

&lt;p&gt;Phase 3 of the roadmap is the team-sync story — Postgres backend, an HTTP API, multiple developers sharing history without sharing a SQLite file. I don't have a date on it. The local SQLite version is fully featured for solo devs and small teams who are fine sharing a file.&lt;/p&gt;

&lt;p&gt;The thing I'd actually like feedback on, if you try this: where does &lt;code&gt;selvedge setup&lt;/code&gt; pick the wrong default? The Cursor and Copilot paths are newer than the Claude Code one — I've used them less, and the test coverage exists but isn't from real-world usage. If something in the wizard surprises you, an issue is the most useful thing.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/masondelan/selvedge" rel="noopener noreferrer"&gt;github.com/masondelan/selvedge&lt;/a&gt; — issues and DMs both work.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>claudecode</category>
      <category>mcp</category>
      <category>opensource</category>
    </item>
    <item>
      <title>The silent problem with AI-written code: the intent evaporates</title>
      <dc:creator>Mason Delan</dc:creator>
      <pubDate>Fri, 24 Apr 2026 03:56:15 +0000</pubDate>
      <link>https://forem.com/masondelan/the-silent-problem-with-ai-written-code-the-intent-evaporates-14c4</link>
      <guid>https://forem.com/masondelan/the-silent-problem-with-ai-written-code-the-intent-evaporates-14c4</guid>
      <description>&lt;p&gt;There's a problem with AI-written code that nobody talks about yet, because most of us haven't been using AI agents long enough for it to bite us.&lt;/p&gt;

&lt;p&gt;The problem is this: &lt;strong&gt;AI agents know exactly why they made every decision. And then the session ends.&lt;/strong&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  What happens with human code
&lt;/h2&gt;

&lt;p&gt;When humans write code, intent leaks everywhere. It's in the commit message ("Add phone field for 2FA rollout"), the PR description, the Slack thread that preceded it, the inline comment that explains the weird edge case. You can reconstruct &lt;em&gt;why&lt;/em&gt; a decision was made months later because the evidence trail is thick.&lt;/p&gt;

&lt;p&gt;This works because humans understand that their code will outlast their memory of writing it.&lt;/p&gt;

&lt;h2&gt;
  
  
  What happens with AI-written code
&lt;/h2&gt;

&lt;p&gt;An AI agent has perfect clarity about why it's making each change — right up until the conversation ends.&lt;/p&gt;

&lt;p&gt;Run &lt;code&gt;git blame&lt;/code&gt; six months later:&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="mi"&gt;3&lt;/span&gt;&lt;span class="n"&gt;e7a991&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Claude&lt;/span&gt; &lt;span class="n"&gt;Code&lt;/span&gt;  &lt;span class="mi"&gt;2025&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;14&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;  &lt;span class="n"&gt;user_tier_v2&lt;/span&gt; &lt;span class="nb"&gt;VARCHAR&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;20&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Commit message: &lt;code&gt;"Update schema"&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;The agent knew why. It added &lt;code&gt;user_tier_v2&lt;/code&gt; to support a grandfathering flag during a pricing migration. It stored the original tier so you could backfill discounts without touching billing history. It was a careful, intentional decision — and that context is completely gone.&lt;/p&gt;

&lt;p&gt;This isn't a hypothetical. If you've been using AI coding tools for more than a few months, you've already hit this wall. You just might not have noticed yet.&lt;/p&gt;




&lt;h2&gt;
  
  
  The pandas moment
&lt;/h2&gt;

&lt;p&gt;When pandas came out, data scientists were doing data manipulation with raw Python loops and NumPy. The problem wasn't that it was &lt;em&gt;impossible&lt;/em&gt; — it was that there was no shared infrastructure for it, so everyone was reinventing the same patterns badly.&lt;/p&gt;

&lt;p&gt;Pandas became essential infrastructure. Not a feature, not a nice-to-have — &lt;em&gt;infrastructure&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;I think codebase change tracking is the same problem for AI-era development. Right now, every team using AI agents heavily is slowly accumulating a codebase full of decisions that made perfect sense when the agent made them and are increasingly opaque to everyone who touches the code afterward.&lt;/p&gt;




&lt;h2&gt;
  
  
  Selvedge
&lt;/h2&gt;

&lt;p&gt;I built &lt;a href="https://github.com/masondelan/selvedge" rel="noopener noreferrer"&gt;Selvedge&lt;/a&gt; to capture that reasoning before it's gone.&lt;/p&gt;

&lt;p&gt;It's an MCP server. AI agents (starting with Claude Code) call it as they work to log structured change events — what changed, when, which agent, which commit, and crucially: &lt;em&gt;why&lt;/em&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;selvedge blame users.stripe_customer_id

  users.stripe_customer_id
  Changed     2026-03-14 11:22:01
  Agent       claude-code
  Commit      9c3f441
  Reasoning   User asked to add Stripe billing — needs customer ID to &lt;span class="nb"&gt;link
              &lt;/span&gt;accounts to subscriptions without storing card details locally.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That &lt;code&gt;Reasoning&lt;/code&gt; field is captured from the agent's context in the moment, before the session ends. It's not generated by Selvedge — Selvedge just captures what the agent already knows and stores it somewhere you can query later.&lt;/p&gt;




&lt;h2&gt;
  
  
  How it works
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Setup is three steps:&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Install:
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;pip &lt;span class="nb"&gt;install &lt;/span&gt;selvedge
&lt;span class="nb"&gt;cd &lt;/span&gt;your-project &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; selvedge init
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;Add to your Claude Code config (&lt;code&gt;~/.claude/config.json&lt;/code&gt;):
&lt;/li&gt;
&lt;/ol&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;"mcpServers"&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;"selvedge"&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;"command"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"selvedge-server"&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;ol&gt;
&lt;li&gt;Add a few lines to your project's &lt;code&gt;CLAUDE.md&lt;/code&gt;:
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;You have access to Selvedge for change tracking.
Call selvedge.log_change immediately after adding, modifying, or removing
any DB column, table, function, API endpoint, dependency, or env variable.
Set reasoning to the user's original request or the problem being solved.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;From then on, your agent logs changes automatically as it works.&lt;/p&gt;




&lt;h2&gt;
  
  
  Querying your history
&lt;/h2&gt;

&lt;p&gt;The CLI is built for how you actually investigate codebases:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# What changed in the users table in the last 30 days?&lt;/span&gt;
selvedge diff &lt;span class="nb"&gt;users&lt;/span&gt; &lt;span class="nt"&gt;--since&lt;/span&gt; 30d

&lt;span class="c"&gt;# What was the last change to payments.amount and why?&lt;/span&gt;
selvedge blame payments.amount

&lt;span class="c"&gt;# Everything related to the Stripe billing feature&lt;/span&gt;
selvedge search &lt;span class="s2"&gt;"stripe"&lt;/span&gt;

&lt;span class="c"&gt;# How often is my agent actually logging changes?&lt;/span&gt;
selvedge stats
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;There's also a changeset system — you can tag related changes under a shared slug (&lt;code&gt;"add-stripe-billing"&lt;/code&gt;) and reconstruct the full scope of a feature across multiple entities later:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;selvedge &lt;span class="nb"&gt;history&lt;/span&gt; &lt;span class="nt"&gt;--changeset&lt;/span&gt; add-stripe-billing
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Backfilling existing projects
&lt;/h2&gt;

&lt;p&gt;If you already have a project with migration files, you don't have to start from zero:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;selvedge import ./migrations/
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It parses raw SQL DDL and Alembic Python files and backfills your schema history. Not as rich as captured reasoning, but better than nothing.&lt;/p&gt;




&lt;h2&gt;
  
  
  What's next
&lt;/h2&gt;

&lt;p&gt;Right now Selvedge uses local SQLite, which works great for individual developers and small teams with a shared volume. Phase 3 is a PostgreSQL backend and HTTP REST API so teams can share a history across machines — that's the path to making this a proper team tool.&lt;/p&gt;

&lt;p&gt;The core insight I keep coming back to: &lt;strong&gt;the diff is git's job. The why is Selvedge's job.&lt;/strong&gt;&lt;/p&gt;




&lt;p&gt;If you've been using Claude Code or Cursor heavily and have felt this pain, I'd love to hear how you've been handling it (or whether you've just been living with it). And if you try Selvedge, feedback on what's missing would go a long way.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Current version: v0.3.1&lt;/strong&gt; — shipped today (April 23, 2026). It's a hardening release: connection-with-retry and &lt;code&gt;PRAGMA busy_timeout = 5000&lt;/code&gt; so concurrent writes are safe under contention (tested against 8 threads writing simultaneously), an explicit &lt;code&gt;schema_migrations&lt;/code&gt; table replacing the old swallow-OperationalError-and-pray ALTER pattern, structured logging under the &lt;code&gt;selvedge.*&lt;/code&gt; namespace (&lt;code&gt;SELVEDGE_LOG_LEVEL=DEBUG&lt;/code&gt; to turn it up), and a frozen public API surface locked in by test. The preceding release (v0.3.0) was a correctness pass that caught a pile of silent-wrong-answer bugs: &lt;code&gt;--since 5m&lt;/code&gt; used to mean 5 months instead of 5 minutes; SQL &lt;code&gt;LIKE&lt;/code&gt; wasn't escaping &lt;code&gt;_&lt;/code&gt; or &lt;code&gt;%&lt;/code&gt; in search queries; &lt;code&gt;CREATE TABLE&lt;/code&gt; import emitted zero events for inline columns; mixed-timezone timestamps sorted incorrectly because &lt;code&gt;-08:00&lt;/code&gt; is less than &lt;code&gt;+00:00&lt;/code&gt; in ASCII. Both are recommended upgrades.&lt;/p&gt;

&lt;p&gt;GitHub: &lt;a href="https://github.com/masondelan/selvedge" rel="noopener noreferrer"&gt;https://github.com/masondelan/selvedge&lt;/a&gt;&lt;br&gt;
Install: &lt;code&gt;pip install selvedge&lt;/code&gt;&lt;/p&gt;

</description>
      <category>ai</category>
      <category>claudecode</category>
      <category>mcp</category>
      <category>opensource</category>
    </item>
  </channel>
</rss>
