<?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: Miguel Shinyenyi</title>
    <description>The latest articles on DEV Community by Miguel Shinyenyi (@miguel_shinyenyi_e2291c8c).</description>
    <link>https://dev.to/miguel_shinyenyi_e2291c8c</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%2F2292980%2F4251fa04-8b57-4cec-bc4a-88c1a8ac7a2a.jpg</url>
      <title>DEV Community: Miguel Shinyenyi</title>
      <link>https://dev.to/miguel_shinyenyi_e2291c8c</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/miguel_shinyenyi_e2291c8c"/>
    <language>en</language>
    <item>
      <title>Building the Umwayi hub landing page on Founding.dev: what happened and how we responded</title>
      <dc:creator>Miguel Shinyenyi</dc:creator>
      <pubDate>Mon, 09 Nov 2026 19:24:22 +0000</pubDate>
      <link>https://dev.to/miguel_shinyenyi_e2291c8c/building-the-umwayi-hub-landing-page-on-foundingdev-what-happened-and-how-we-responded-307c</link>
      <guid>https://dev.to/miguel_shinyenyi_e2291c8c/building-the-umwayi-hub-landing-page-on-foundingdev-what-happened-and-how-we-responded-307c</guid>
      <description>&lt;p&gt;I build the Umwayi hub in public. It is an AI operating system that grew out of my personal notebook. One backend engineer in Nairobi builds it, and it is pre-release. The code has no front door, so for the Founding.dev design hackathon I designed one.&lt;/p&gt;

&lt;p&gt;Live page: &lt;a href="https://umwayi-hub.foundingdev.com/" rel="noopener noreferrer"&gt;https://umwayi-hub.foundingdev.com/&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  What the page is for
&lt;/h2&gt;

&lt;p&gt;A stranger should understand the hub in one minute. The headline is "Every AI helper needs a shepherd." The hub gives every AI helper one of three answers before it acts: Yes, No, or Ask me first.&lt;/p&gt;

&lt;p&gt;I did not want a mock-up. The demo on the page shows the real hub as it exists: its rules, its queue, its archive and its logbook, taken from the public repository. The build window ran from Nov 6 to Nov 10, about three hours a day.&lt;/p&gt;

&lt;h2&gt;
  
  
  How the build went
&lt;/h2&gt;

&lt;p&gt;I planned the page with Claude before I touched the builder. We wrote the prompts in advance, one at a time, so each one could stand alone.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Prompt 1 built the page: hero, timeline, four parts, roadmap, FAQ.&lt;/li&gt;
&lt;li&gt;Prompt 2 built the demo from real hub content.&lt;/li&gt;
&lt;li&gt;Prompt 3 added the dark theme, Nightwatch.&lt;/li&gt;
&lt;li&gt;Prompt 4 finished the roadmap and FAQ.&lt;/li&gt;
&lt;li&gt;Prompt 5 audited the page.&lt;/li&gt;
&lt;li&gt;Prompt 6 turned the four parts into one hill scene you can walk into.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The first paste went wrong. The builder sent only the first line, because a line break submits the message. From then on we pasted every prompt as one line.&lt;/p&gt;

&lt;h2&gt;
  
  
  What went wrong on screen, and what we did
&lt;/h2&gt;

&lt;p&gt;The builder reports what it saw, and it often saw one view. So after each prompt I looked at the page myself and wrote down what was wrong. The next prompt fixed exactly that.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Robot shepherd, gate lamps and a logbook printer went in on Nov 7. The lamp labels were about 6.5 pixels tall and unreadable, and a lamp plate overlapped the robot's arm. When the lantern became the robot's head, the night lantern disappeared.&lt;/li&gt;
&lt;li&gt;The next pass added a conveyor belt and a vault barn. The lamp sign came out far too large, nearly as tall as the fence. The robot, barn and fence were different scales. The barn door overlapped its shelves.&lt;/li&gt;
&lt;li&gt;Prompt D set one scale for every object and added scroll motion. The Parts scene was still about 60 percent empty sky, with small objects in a strip at the bottom.&lt;/li&gt;
&lt;li&gt;Prompt E cropped the sky and scaled objects up by about 1.5. Two sheep were left floating above the fence.&lt;/li&gt;
&lt;li&gt;Prompt F put everything on one ground line. Three hero sheep still merged into one shape, and the robot overlapped the end of the pen fence.&lt;/li&gt;
&lt;li&gt;Prompt G fixed the hero crop and the sheep spacing, and made the Parts scene fit at 375 pixels.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Six passes, and each one fixed what the one before it left. The builder's own report did not catch most of these.&lt;/p&gt;

&lt;h2&gt;
  
  
  How we kept it safe to change
&lt;/h2&gt;

&lt;p&gt;After every prompt I wrote down the commit and what it changed, so I could go back. Every pass has a restore point. If a prompt made the page worse, I could revert to the commit before it.&lt;/p&gt;

&lt;p&gt;I also set a credit rule. The hackathon gave $10 of builder credits, plus extra I added. I set a $3 reserve. Each machine-imagery prompt cost about $0.40. When a text pass needed more, I approved going below the reserve myself, so the decision stayed with me.&lt;/p&gt;

&lt;h2&gt;
  
  
  Keeping the page honest
&lt;/h2&gt;

&lt;p&gt;The page started with a rule: it may not claim more than the hub does. Helpers are marked as coming, not built. Roadmap dates carry the label "Plan, dates may change." Nothing on it is marked live.&lt;/p&gt;

&lt;p&gt;The hub moved while I designed. On Nov 7 I found wording that said the hub was one check. It was code in layers. We rewrote the text. On Nov 8 we replaced the roadmap with six cards that match the real timeline. On Nov 9 we updated the text to the current phase of the hub.&lt;/p&gt;

&lt;h2&gt;
  
  
  Where it is weak
&lt;/h2&gt;

&lt;p&gt;The builder reported one view at a time, and I checked the night view at desktop width after each pass. The light theme on a phone works; I have confirmed that. I have not confirmed the page at night on a phone, or at tablet width, after the last changes. Look at it yourself in both themes and at three sizes.&lt;/p&gt;

&lt;p&gt;I also left the Helpers heading as it was written on Nov 7. The roadmap has moved since, and the two no longer say the same thing.&lt;/p&gt;

&lt;h2&gt;
  
  
  What I took from it
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;Write the prompts first, and send them one at a time.&lt;/li&gt;
&lt;li&gt;Look at every result yourself. The builder reports the view it saw.&lt;/li&gt;
&lt;li&gt;Keep a restore point after each change, and a credit limit you decide.&lt;/li&gt;
&lt;li&gt;Keep the page text in step with the real work.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The page is published. The hackathon closes Tue Nov 10, 10:59 AM Nairobi. The build story of the hub itself comes with my Kiroween submission on Dec 3.&lt;/p&gt;

&lt;p&gt;The code: &lt;a href="https://github.com/Miguel-Shinyenyi/umwayi-os" rel="noopener noreferrer"&gt;https://github.com/Miguel-Shinyenyi/umwayi-os&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If you have used an AI page builder, what did you have to fix after its first pass?&lt;/p&gt;




&lt;p&gt;Originally published on &lt;a href="https://miguel-shinyenyi.github.io/miguel-site/tech/building-a-landing-page-on-founding-dev/" rel="noopener noreferrer"&gt;my site&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>foundingdev</category>
      <category>design</category>
      <category>umwayi</category>
      <category>buildinpublic</category>
    </item>
    <item>
      <title>Appearance versus reality, from three lines in an interview</title>
      <dc:creator>Miguel Shinyenyi</dc:creator>
      <pubDate>Mon, 09 Nov 2026 07:25:35 +0000</pubDate>
      <link>https://dev.to/miguel_shinyenyi_e2291c8c/appearance-versus-reality-from-three-lines-in-an-interview-2bf4</link>
      <guid>https://dev.to/miguel_shinyenyi_e2291c8c/appearance-versus-reality-from-three-lines-in-an-interview-2bf4</guid>
      <description>&lt;h2&gt;
  
  
  The source
&lt;/h2&gt;

&lt;p&gt;In late November 2025, Nikhil Kamath interviewed Elon Musk on his People by WTF podcast. I wrote down three ideas from it in my notes. Before I used them, I looked for reports of the interview. Two of the three held up. One detail in my notes did not.&lt;/p&gt;

&lt;p&gt;I am quoting a public figure on ideas, not endorsing him. I did not check his own record. These ideas stand or fall without it.&lt;/p&gt;

&lt;h2&gt;
  
  
  Idea one: appearance and reality
&lt;/h2&gt;

&lt;p&gt;Reports of the interview say he called it easy to give money away to get the appearance of goodness, and hard to give it in a way that truly helps. I see the same split in my own work.&lt;/p&gt;

&lt;p&gt;A commit count is an appearance. So is a count of merged pull requests. Both can rise without helping anyone. The reality is whether the reporter's problem got solved, and no git log records that. In my open-source work, a pull request can merge and leave the reporter's problem open. Another can close unmerged because the maintainers shipped their own fix, and the problem is still solved. The count rates the first higher than the second. The reporter would not.&lt;/p&gt;

&lt;h2&gt;
  
  
  Idea two: happiness is indirect
&lt;/h2&gt;

&lt;p&gt;He said you cannot pursue happiness directly. One report names meaningful work, study, and time with friends and loved ones. My note says "going to the gym". None of the sources I read mention the gym, so I cannot attach it to him. It is a good example anyway, so I am keeping it as mine: I do not get happy by trying to be happy. I get there by sleeping, moving, and seeing people I like.&lt;/p&gt;

&lt;h2&gt;
  
  
  Idea three: value first, money after
&lt;/h2&gt;

&lt;p&gt;His advice, as reported: build useful products and services, and money follows. Create more value than you take. My note says "output more than you input". I read this as a test for a project, not a promise of income. Ask who gets something useful from it. If the honest answer is "only me, and only on paper", it is probably not worth the hours.&lt;/p&gt;

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

&lt;p&gt;I added a progress digest to my hub. It counts commits and merged pull requests by week. It cannot count value. Its README says so, and I read each digest next to my journal, where I write what actually got solved.&lt;/p&gt;

&lt;h2&gt;
  
  
  What I might be wrong about
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;A person with enormous wealth may talk about money differently than someone building from nothing. These ideas may not transfer cleanly.&lt;/li&gt;
&lt;li&gt;Money does not always follow value. Useful work often goes unpaid. I read the idea as a direction.&lt;/li&gt;
&lt;li&gt;I read reports, not the full recording. Quotes in articles can be trimmed or reordered.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  What I took from it
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;Counts of activity show appearance. Whether someone's problem got solved shows reality.&lt;/li&gt;
&lt;li&gt;I cannot pursue happiness directly, so I keep the habits that lead toward it: sleep, movement, people.&lt;/li&gt;
&lt;li&gt;For any project, ask who gets something useful from it besides me.&lt;/li&gt;
&lt;li&gt;If I cannot verify a detail in my notes, I mark it as mine or I drop it.&lt;/li&gt;
&lt;/ol&gt;




&lt;p&gt;Originally published on &lt;a href="https://miguel-shinyenyi.github.io/miguel-site/philosophy/appearance-versus-reality/" rel="noopener noreferrer"&gt;my site&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>work</category>
      <category>measurement</category>
      <category>learning</category>
    </item>
    <item>
      <title>Do the rules that stop an AI also stop us?</title>
      <dc:creator>Miguel Shinyenyi</dc:creator>
      <pubDate>Sun, 08 Nov 2026 05:06:02 +0000</pubDate>
      <link>https://dev.to/miguel_shinyenyi_e2291c8c/do-the-rules-that-stop-an-ai-also-stop-us-2m53</link>
      <guid>https://dev.to/miguel_shinyenyi_e2291c8c/do-the-rules-that-stop-an-ai-also-stop-us-2m53</guid>
      <description>&lt;h2&gt;
  
  
  What this is
&lt;/h2&gt;

&lt;p&gt;These are my notes from November 8, written after reading parts of Sapiens by Yuval Noah Harari and while building a rules layer for AI helpers. I am not a neuroscientist or a machine learning researcher. The claims about brains and models are my understanding, and I mark where I am unsure. I have not checked the Sapiens points against the book page by page.&lt;/p&gt;

&lt;h2&gt;
  
  
  The comparison I started with
&lt;/h2&gt;

&lt;p&gt;An AI model is trained on a large amount of text. Training sets numbers called weights, and the weights shape what the model says next. A person is raised among people. Family, school and culture shape what the person believes and what the person does next.&lt;/p&gt;

&lt;p&gt;Both end up with something that works like a settled view. Neither can fully predict what it will output in a new situation.&lt;/p&gt;

&lt;h2&gt;
  
  
  Where the comparison holds
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Both are shaped by what they were exposed to. A model trained on poor text gives poor answers. A person raised on poor information holds poor beliefs.&lt;/li&gt;
&lt;li&gt;Both can be wrong with confidence.&lt;/li&gt;
&lt;li&gt;Both can produce something their history does not predict. A person can drop the beliefs of their upbringing. A model can produce text that no reliable source supports. These are different events, and I do not treat them as the same.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Where it breaks
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;As far as I know, a model does not visibly weigh an earlier belief against new evidence. When it hallucinates, it produces fluent text that is not grounded in a reliable source. Some models carry internal signals about their own uncertainty, so I will not say there is nothing behind the text. A person who changes a belief usually felt the conflict first. I do not know whether a model has anything like that feeling. As far as I know, nobody has shown that it does, so I will not claim it.&lt;/li&gt;
&lt;li&gt;A person keeps learning after childhood, from one experience at a time. A deployed model has fixed weights. Inside one conversation it can adapt to what you tell it, but that is not learning, and it is gone when the conversation ends.&lt;/li&gt;
&lt;li&gt;Determinism is not the same on both sides. A model run with fixed settings can give the same output twice, but it is not guaranteed in practice, because of rounding in floating point math and how requests are batched together. For brains, whether they are deterministic is still an open argument. I will not settle it here.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;So I would say the model resembles a person in how it was shaped. It does not resemble a person in how it changes its mind.&lt;/p&gt;

&lt;h2&gt;
  
  
  What the rules do
&lt;/h2&gt;

&lt;p&gt;When I build checks around an AI helper, I write down what it may do, what it may not do, and what it must ask me first. The check runs as code. If the action is not listed, the answer is Ask me first.&lt;/p&gt;

&lt;p&gt;Harari describes imagined orders: money, empires, religions. They work because many people believe in them. I recorded his argument like this: cultures that were once separate and isolated were drawn together by universal orders, the monetary order, the imperial order and religion, and money succeeded where gods and kings failed. The line I added myself is that money feeds the body while religion and politics mostly comfort the mind. I do not know whether that last part is his.&lt;/p&gt;

&lt;p&gt;Here is the difference I keep coming back to. An imagined order needs belief. It also needs people to enforce it, and people sometimes do not. A rule file in my system needs neither. The model does not have to agree with it. The check runs outside the model. The model cannot talk its way past it, as long as it cannot edit the rules file and cannot act without going through the check. Both of those conditions are things I have to build and test.&lt;/p&gt;

&lt;p&gt;The two are alike in one place. Someone wrote the rules. Someone decided what was allowed. The check is exact, but the choices behind it are human, can be wrong, and can be changed. That is also true of laws.&lt;/p&gt;

&lt;h2&gt;
  
  
  What a rule gives back
&lt;/h2&gt;

&lt;p&gt;I wrote down another note this week. A kite flies when it is tied to a string, and it falls when the string is let go. Something I take as holding me back may be what lifts me. I try to notice which of my limits work that way.&lt;/p&gt;

&lt;p&gt;A rule that stops an AI from moving money lets me give it other work without watching every step. The limit is what makes the trust possible. In my own life, a fixed schedule has done the same.&lt;/p&gt;

&lt;p&gt;Harari also says tension and unresolved dilemmas drive creativity in a culture. I think a system needs some of that too. My rule file answers every case, but the cases I did not list go to me. That keeps a human decision in the places that are new.&lt;/p&gt;

&lt;h2&gt;
  
  
  What I still do not know
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Whether a model can hold two conflicting views in a way that matters, or whether that is only how its output looks.&lt;/li&gt;
&lt;li&gt;Whether a checker outside the model could ever be complete. Mine is not. It fails safe, and that is a weaker claim.&lt;/li&gt;
&lt;li&gt;Whether the rules I write for helpers say more about the helpers or about me.&lt;/li&gt;
&lt;/ul&gt;




&lt;p&gt;Originally published on &lt;a href="https://miguel-shinyenyi.github.io/miguel-site/philosophy/rules-that-stop-an-ai-and-rules-that-stop-us/" rel="noopener noreferrer"&gt;my site&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>reasoning</category>
      <category>reading</category>
    </item>
    <item>
      <title>Come with a question, not a verdict</title>
      <dc:creator>Miguel Shinyenyi</dc:creator>
      <pubDate>Sun, 08 Nov 2026 05:05:31 +0000</pubDate>
      <link>https://dev.to/miguel_shinyenyi_e2291c8c/come-with-a-question-not-a-verdict-48cc</link>
      <guid>https://dev.to/miguel_shinyenyi_e2291c8c/come-with-a-question-not-a-verdict-48cc</guid>
      <description>&lt;h2&gt;
  
  
  The verdict is already written
&lt;/h2&gt;

&lt;p&gt;I have been paying attention to how arguments go, mine included. Someone says a first sentence. The other person has the reply ready before the sentence ends. The reply is a verdict. It only needs a signature.&lt;/p&gt;

&lt;p&gt;A verdict ends the inquiry. If I already know you are wrong, I have no reason to learn why you think what you think. I wait for my turn. You do the same. Two people can talk for an hour and neither learns anything.&lt;/p&gt;

&lt;h2&gt;
  
  
  What a verdict costs
&lt;/h2&gt;

&lt;p&gt;It costs me information. The person across from me holds facts I do not have: what they saw, what they lost, what they read. A question gets me those facts. A verdict gets me a defended position.&lt;/p&gt;

&lt;p&gt;It also costs them. In my experience, people who feel judged often stop explaining and repeat their position louder. I then read the louder repetition as proof I was right. That is how the loop feeds itself.&lt;/p&gt;

&lt;p&gt;I suspect curiosity dies this way, one conversation at a time. Nobody may decide to stop being curious. People may learn that questions get punished and verdicts get rewarded.&lt;/p&gt;

&lt;h2&gt;
  
  
  A check to run before I reply
&lt;/h2&gt;

&lt;p&gt;I am trying three steps. They are small on purpose.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Say the other person's view back to them in my own words, and ask if I got it right. If they say no, I was about to argue with something they never said.&lt;/li&gt;
&lt;li&gt;Ask one question whose answer I do not know. "What would change your mind?" works. So does "What did you see that made you think that?"&lt;/li&gt;
&lt;li&gt;Name what would change my own mind before I speak. My view is that if nothing could, I do not have a position. I have a verdict.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In my first tries it took about two minutes. It does not mean I agree. I can ask a real question and still disagree after I hear the answer.&lt;/p&gt;

&lt;h2&gt;
  
  
  What I might be wrong about
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Some questions are settled. If someone says the earth is flat, a long curious conversation may waste both our time. I do not have a clean rule for where that line sits.&lt;/li&gt;
&lt;li&gt;A question can be a verdict in disguise. "Don't you think that's a bit naive?" is not a question. Asking well takes more than adding a question mark.&lt;/li&gt;
&lt;li&gt;I have tested this on myself in a few conversations, not on a large sample. The effect I describe is what I noticed, not something I measured.&lt;/li&gt;
&lt;li&gt;Some people argue to win, and no question will change that. I still choose how I show up. I cannot choose how they do.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  What I took from it
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;A verdict ends the inquiry before it starts. A question keeps it open.&lt;/li&gt;
&lt;li&gt;People often stop explaining when they feel judged, and I then take their louder repetition as proof I was right.&lt;/li&gt;
&lt;li&gt;Before replying: restate their view, ask one question I cannot answer, and name what would change my mind.&lt;/li&gt;
&lt;li&gt;Asking a question does not mean I agree. It means I want the facts first.&lt;/li&gt;
&lt;li&gt;If I cannot name what would change my mind, I am holding a verdict.&lt;/li&gt;
&lt;/ol&gt;




&lt;p&gt;Originally published on &lt;a href="https://miguel-shinyenyi.github.io/miguel-site/philosophy/come-with-a-question-not-a-verdict/" rel="noopener noreferrer"&gt;my site&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>reasoning</category>
      <category>learning</category>
      <category>conversation</category>
    </item>
    <item>
      <title>A Folder Is Not a Brain Until You Measure It</title>
      <dc:creator>Miguel Shinyenyi</dc:creator>
      <pubDate>Tue, 03 Nov 2026 08:05:01 +0000</pubDate>
      <link>https://dev.to/miguel_shinyenyi_e2291c8c/a-folder-is-not-a-brain-until-you-measure-it-8gm</link>
      <guid>https://dev.to/miguel_shinyenyi_e2291c8c/a-folder-is-not-a-brain-until-you-measure-it-8gm</guid>
      <description>&lt;h2&gt;
  
  
  What I wanted
&lt;/h2&gt;

&lt;p&gt;I wanted an AI that acts on what I mean, not on the first reading of my words. I wanted it steady and quiet when I am rushing.&lt;/p&gt;

&lt;p&gt;So I built a folder. It holds a short identity, rules that came from mistakes, a habit of understanding a problem before solving it, and an archive. I called it a brain. I thought of the archive as childhood memory: vague, but still part of who I am.&lt;/p&gt;

&lt;p&gt;That was a belief, not a result. This article is what happened when I checked it.&lt;/p&gt;

&lt;h2&gt;
  
  
  What the studies say about eager AI
&lt;/h2&gt;

&lt;p&gt;Eager execution is measured now. I did not need to argue it.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;One benchmark ran about 7,500 coding-agent runs on tasks where doing extra was wrong. The mean rate of out-of-scope actions was 10.8%. The same base model ranged from 1.1% to 27.7% depending on the tool wrapped around it.&lt;/li&gt;
&lt;li&gt;Another benchmark gave agents underspecified infrastructure instructions. Between 55.8% and 67.8% of the runs that acted crossed a boundary.&lt;/li&gt;
&lt;li&gt;A third paper added a second agent that watches for missing context and forces a question. Resolve rate rose from 61.2% to 69.4%. Cost per task rose from $2.03 to $3.50. The user in that test was simulated.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Eager execution is real, large, and depends on the harness as much as the model.&lt;/p&gt;

&lt;h2&gt;
  
  
  What the studies say about folders like mine
&lt;/h2&gt;

&lt;p&gt;A 2026 study tested repository context files, the AGENTS.md kind, on coding agents.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Files written by a model lowered success by 0.5% to 2%.&lt;/li&gt;
&lt;li&gt;Files written by a developer raised success by about 4%.&lt;/li&gt;
&lt;li&gt;Both kinds raised reasoning tokens by 14% to 22%.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The agents obeyed the files. The files that restated what the repository already said did not help. This matters to me. A model drafts much of my hub. A file I never read closely can cost more than it gives.&lt;/p&gt;

&lt;p&gt;On identity, persona research finds drift. One study saw a model leave its system prompt within eight rounds. Another ran more than 100 rounds and saw personas revert toward the model's default. Larger models drifted less, and none stayed fixed.&lt;/p&gt;

&lt;h2&gt;
  
  
  What others already built
&lt;/h2&gt;

&lt;p&gt;My design is not new. Letta, which grew out of MemGPT, splits in-context core memory from archival memory. It also runs a second agent that rewrites memory while the first one is idle. Anthropic's memory tool gives the model a directory of files it can read and write. A 2026 survey of agent memory says forgetting is rarely tested and warns of memory blindness, where an important fact sits in cold storage and is never fetched.&lt;/p&gt;

&lt;p&gt;If I claim a new architecture, I am wrong. If I claim a measured result on one open model, I can be right.&lt;/p&gt;

&lt;h2&gt;
  
  
  Where my human memory comparison fails
&lt;/h2&gt;

&lt;p&gt;Some of it holds. A small core that is always loaded, plus a store reached by cues, is a sensible answer to limited working capacity. One review of memory research describes detailed episodes turning into gist-like versions over time. Another line of work says gist and exact detail are stored in parallel.&lt;/p&gt;

&lt;p&gt;Three parts do not hold.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A person's early experience keeps shaping them because the brain changes. A model's weights do not change. An archived file that nobody loads has no effect at all.&lt;/li&gt;
&lt;li&gt;Human gist comes from lossy storage and produces false memories. My archive can be exact. So I should keep the original text, and mark every summary as derived and link it to its source by checksum.&lt;/li&gt;
&lt;li&gt;In people, recalling a memory can alter it. Each time I rewrite my core file, I risk the same. A rule written from one mistake can lose its conditions and grow too broad.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I now use the comparison as a reason to try a design. I do not use it as proof.&lt;/p&gt;

&lt;h2&gt;
  
  
  What I think is true now
&lt;/h2&gt;

&lt;p&gt;One narrow claim looks supported by nearby evidence: short, human-written rules and a stated scope can cut out-of-scope actions. The effect is small, depends on the harness, and costs tokens.&lt;/p&gt;

&lt;p&gt;Two bigger claims are not supported. A folder does not make a brain. A text file does not give an AI an identity. It gives it a policy and a style. If I say more, I owe a measurement.&lt;/p&gt;

&lt;h2&gt;
  
  
  Where I will test it
&lt;/h2&gt;

&lt;p&gt;I joined the Meta Global AI Developer Hackathon, which runs from October 27 to November 4, 2026. I entered as a solo builder in the Indie track. Entries must use Meta models. I will use Muse Spark Open, an open-weights model, served on Baseten.&lt;/p&gt;

&lt;p&gt;I will not test the folder on its own. A test with no user is easy to bend toward the answer I want. I am building a small open-source secretary for savings groups, the chamas many Kenyans use to save together. A treasurer speaks a note or photographs a paper ledger page. The agent proposes ledger entries and asks a question when a note is ambiguous, for example when two members share a name. The treasurer approves everything. The agent moves no money, scores no one and sends nothing.&lt;/p&gt;

&lt;p&gt;The restraint ideas from this article sit inside that agent. The tests are part of the entry, with the plan and protocol public in the repository before I run them. I have not built any of it yet. People already make chama apps, such as Chamasoft and M-Chama, so I am not claiming this is the first. Nobody has used mine. Whether treasurers want it is a question I still have to ask them.&lt;/p&gt;

&lt;h2&gt;
  
  
  What I will test
&lt;/h2&gt;

&lt;p&gt;I will run it on Muse Spark Open in the first week of the event, with the hypotheses written down first.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Curated rules lower wrong guesses on ambiguous notes, such as a name that matches two members. The comparison that counts is against a generic "ask when unsure" block of the same length, not against nothing.&lt;/li&gt;
&lt;li&gt;A core plus a traceable archive keeps stale-fact updates and archived needles better than truncation or plain retrieval at the same token budget.&lt;/li&gt;
&lt;li&gt;Rule adherence survives compaction, when a long conversation is summarised to continue.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Controls: a placebo text of equal length, scenarios split into development and a frozen test set, a check that the model does not simply always ask, and cost reported next to every effect. With about 40 test scenarios I can only detect effects of roughly 15 points or more. A null result gets published.&lt;/p&gt;

&lt;h2&gt;
  
  
  What I do not know
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;How Muse Spark Open follows instructions, and whether it reads handwriting and voice well. I check this on day one.&lt;/li&gt;
&lt;li&gt;Whether treasurers want this at all.&lt;/li&gt;
&lt;li&gt;Whether my rules fit my own test cases because I wrote both.&lt;/li&gt;
&lt;li&gt;Whether any effect survives a second model.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Sources
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://www.sri.inf.ethz.ch/publications/gloaguen2026agentsmd" rel="noopener noreferrer"&gt;Evaluating AGENTS.md: Are Repository-Level Context Files Helpful for Coding Agents?&lt;/a&gt; and the &lt;a href="https://academy.dair.ai/blog/agents-md-evaluation" rel="noopener noreferrer"&gt;summary I read&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href="https://arxiv.org/pdf/2605.18583" rel="noopener noreferrer"&gt;Overeager Coding Agents: Measuring Out-of-Scope Actions on Benign Tasks&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://arxiv.org/pdf/2607.02294" rel="noopener noreferrer"&gt;Coding Agents Are Guessing: Measuring Action-Boundary Violations in Underspecified DevOps Instructions&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.alphaxiv.org/abs/2603.26233" rel="noopener noreferrer"&gt;Ask or Assume? Uncertainty-Aware Clarification-Seeking in Coding Agents&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://arxiv.org/abs/2402.10962" rel="noopener noreferrer"&gt;Measuring and Controlling Persona Drift in Language Model Dialogs&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://arxiv.org/pdf/2512.12775" rel="noopener noreferrer"&gt;Persistent Personas? Role-Playing, Instruction Following, and Safety in Extended Interactions&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://arxiv.org/pdf/2603.07670" rel="noopener noreferrer"&gt;Memory for Autonomous LLM Agents: Mechanisms, Evaluation, and Emerging Frontiers&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://letta.com/blog/sleep-time-compute" rel="noopener noreferrer"&gt;Sleep-time compute, Letta&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://claude.com/blog/context-management" rel="noopener noreferrer"&gt;Context management, Anthropic&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://cerebralvalley.ai/e/meta-ai-developer-hackathon/details" rel="noopener noreferrer"&gt;Meta Global AI Developer Hackathon, event page&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.cambridge.org/core/product/F50631D35ED93130B0E2D58889D00F34" rel="noopener noreferrer"&gt;Memory Transformation and Systems Consolidation, Winocur and Moscovitch (abstract)&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I read the abstracts or summaries of the memory-science sources, not the full papers.&lt;/p&gt;

&lt;h2&gt;
  
  
  What I took from it
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;Check a belief against studies before building more on it.&lt;/li&gt;
&lt;li&gt;Keep rules short, human-written and specific. A file that repeats what the repository says costs tokens and adds nothing.&lt;/li&gt;
&lt;li&gt;Compare against a placebo and a generic version. Beating nothing proves nothing.&lt;/li&gt;
&lt;li&gt;Keep the original text, and link every summary to it. An AI can be lossless where a person cannot.&lt;/li&gt;
&lt;li&gt;Say "persona and rules file" until a measurement earns the word "identity".&lt;/li&gt;
&lt;/ol&gt;




&lt;p&gt;Originally published on &lt;a href="https://miguel-shinyenyi.github.io/miguel-site/tech/a-folder-is-not-a-brain-until-you-measure-it/" rel="noopener noreferrer"&gt;my site&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>agents</category>
      <category>memory</category>
      <category>evaluation</category>
    </item>
    <item>
      <title>Stay Close Behind the Code</title>
      <dc:creator>Miguel Shinyenyi</dc:creator>
      <pubDate>Mon, 26 Oct 2026 11:11:32 +0000</pubDate>
      <link>https://dev.to/miguel_shinyenyi_e2291c8c/stay-close-behind-the-code-1940</link>
      <guid>https://dev.to/miguel_shinyenyi_e2291c8c/stay-close-behind-the-code-1940</guid>
      <description>&lt;h2&gt;
  
  
  What I notice
&lt;/h2&gt;

&lt;p&gt;AI writes more code in an hour than I can read in a day. When I watch the volume grow, I feel pressure. Other people seem to ship more. I feel I should add more tools, more agents and more lines.&lt;/p&gt;

&lt;p&gt;I wrote this from my own notes. I have not checked them against a study or a talk. They describe what I see in my own work.&lt;/p&gt;

&lt;h2&gt;
  
  
  Three feelings behind the hype
&lt;/h2&gt;

&lt;p&gt;Code carries the feelings of the person who wrote it. Three feelings sit behind the hype.&lt;/p&gt;

&lt;p&gt;Code written in a hype cycle carries desperation and fear of missing out. I wrote it fast because I thought I would fall behind. I cannot tell you why it works, so I do not trust it. Nobody else trusts it either.&lt;/p&gt;

&lt;p&gt;The third feeling is overwhelm. There is so much to do, so many tools to learn and so much new code to read, that I end up doing nothing. I think this feeling is one cause of the hype, not only a result of it. It pushes people to chase the next thing because finishing a small thing feels pointless next to the pile. I have not checked that. It is what I see in myself.&lt;/p&gt;

&lt;p&gt;Code I understand carries a calm kind of feeling. I know what it does and where it stops. That feeling takes time to earn. It does not come from volume.&lt;/p&gt;

&lt;p&gt;For code to be worth something to another person, it needs my time and my feelings in it. I cannot add either by prompting faster.&lt;/p&gt;

&lt;h2&gt;
  
  
  Let AI write it, and stay close behind
&lt;/h2&gt;

&lt;p&gt;I do not say you should write every line by hand. Let AI write the code. Stay one step behind it and understand each part as it appears.&lt;/p&gt;

&lt;p&gt;My order is this.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Understand the people. Problems come from patterns where people struggled.&lt;/li&gt;
&lt;li&gt;Write the code, preferably with AI.&lt;/li&gt;
&lt;li&gt;Stop and check that the output matches what I meant.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The third step is the hard one, because I cannot measure "what I meant" until I have said it in one sentence. Patterns, constants and outliers also take time to see. If I rush, I miss all three.&lt;/p&gt;

&lt;p&gt;If I only write code, I should ask who I am helping.&lt;/p&gt;

&lt;h2&gt;
  
  
  The cycle I follow
&lt;/h2&gt;

&lt;p&gt;Every step I take goes round the same cycle.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Understand things as they are, not as I want them to be.&lt;/li&gt;
&lt;li&gt;Let AI write the code for what I understood is needed.&lt;/li&gt;
&lt;li&gt;Check that the output matches what I meant.&lt;/li&gt;
&lt;li&gt;Weigh the consequences before I act. Every action has some. I want the change to do more good than harm, and I want to know how to undo it.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Then I start again with the next step. The first step is the hard one. When I want something to be true, I read the code as if it already were. The ledger check below exists because a system cannot afford that wish.&lt;/p&gt;

&lt;h2&gt;
  
  
  A check that stops the work
&lt;/h2&gt;

&lt;p&gt;My settlement engine has a check that makes the work stop. Each account stores a balance, and each account has ledger entries. The two must agree. This is the service that compares them:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;verify&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;LedgerAccount&lt;/span&gt; &lt;span class="n"&gt;account&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="nc"&gt;BigDecimal&lt;/span&gt; &lt;span class="n"&gt;computed&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;ledgerEntryRepository&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;sumNetByAccountId&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;account&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getId&lt;/span&gt;&lt;span class="o"&gt;());&lt;/span&gt;
    &lt;span class="nc"&gt;BigDecimal&lt;/span&gt; &lt;span class="n"&gt;stored&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;account&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getBalance&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;stored&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;compareTo&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;computed&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ledgerMismatchRepository&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;findByAccountIdAndResolutionStatus&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;account&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getId&lt;/span&gt;&lt;span class="o"&gt;(),&lt;/span&gt;
            &lt;span class="nc"&gt;MismatchResolutionStatus&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;OPEN&lt;/span&gt;&lt;span class="o"&gt;).&lt;/span&gt;&lt;span class="na"&gt;isEmpty&lt;/span&gt;&lt;span class="o"&gt;())&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;ledgerMismatchRepository&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;save&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;LedgerMismatch&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="no"&gt;UUID&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;randomUUID&lt;/span&gt;&lt;span class="o"&gt;(),&lt;/span&gt; &lt;span class="n"&gt;account&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getId&lt;/span&gt;&lt;span class="o"&gt;(),&lt;/span&gt; &lt;span class="n"&gt;stored&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;computed&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
                &lt;span class="s"&gt;"Stored balance "&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;stored&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="s"&gt;" does not match net of ledger entries "&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;computed&lt;/span&gt;&lt;span class="o"&gt;));&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
    &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;LedgerInconsistencyException&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;account&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getId&lt;/span&gt;&lt;span class="o"&gt;(),&lt;/span&gt; &lt;span class="n"&gt;stored&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;computed&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;When the numbers differ, it records the mismatch for a person to review, and then it always throws. The caller never receives a balance the ledger does not back. The account endpoint runs this check before it does anything else with the account.&lt;/p&gt;

&lt;p&gt;This code does not help me ship faster. It makes me stop and ascertain. It is the same habit I want in my own work: before the next step, check that this one matches what I meant.&lt;/p&gt;

&lt;p&gt;I verified the code above against the repository on 2026-10-16. I did not run it for this article.&lt;/p&gt;

&lt;h2&gt;
  
  
  A step I skipped
&lt;/h2&gt;

&lt;p&gt;On 2026-07-11 I committed a file called &lt;code&gt;mvnw&lt;/code&gt;. It looked like the Maven Wrapper. It was four lines that pointed at one folder on my own machine, because I had no system-wide Maven on that machine.&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;# shortened&lt;/span&gt;
&lt;span class="nv"&gt;MVN_HOME&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$HOME&lt;/span&gt;&lt;span class="s2"&gt;/.m2/wrapper/dists/apache-maven-3.9.9-bin/.../apache-maven-3.9.9"&lt;/span&gt;
&lt;span class="nb"&gt;exec&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$MVN_HOME&lt;/span&gt;&lt;span class="s2"&gt;/bin/mvn"&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$@&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It worked for me. It failed on the first CI run, because that folder does not exist on any other machine. I fixed it on 2026-07-17, six days and 23 commits later, by regenerating the real wrapper. The notes in the project say what went wrong: I replaced the wrapper when I only needed to fix my path.&lt;/p&gt;

&lt;p&gt;I see two of the failure modes below in that story. I skipped a step, and I put a patch on a problem I had not understood.&lt;/p&gt;

&lt;h2&gt;
  
  
  Eight ways I get lost
&lt;/h2&gt;

&lt;p&gt;These are the names I use. Each has a sign and a remedy.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Forming. The right question, the wrong answer. I ask more questions until I know the goal and how to approach it.&lt;/li&gt;
&lt;li&gt;Dislodging. I am stuck in a rut. I accept that the approach is not working and restart.&lt;/li&gt;
&lt;li&gt;Assumption. The wrong question, the right answer. I go back and understand the goal.&lt;/li&gt;
&lt;li&gt;Location. So close, so far. I skipped an important step. I slow down and take every step.&lt;/li&gt;
&lt;li&gt;Achievement. A band aid on a broken bone. If the whole codebase is poor, I rewrite it.&lt;/li&gt;
&lt;li&gt;Progression. I fall behind without noticing, because AI took over code I do not understand. I stop and read.&lt;/li&gt;
&lt;li&gt;Interruption. Someone breaks the train of thought that was finding the goal. I know the goal best, and I deal with the humans.&lt;/li&gt;
&lt;li&gt;Mislead. A suggestion leads me away from the goal. I check each suggestion against the goal first.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  What I took from it
&lt;/h2&gt;

&lt;p&gt;This list is a draft for me to correct.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Understand things as they are before I change them. Then let AI write what I understood is needed.&lt;/li&gt;
&lt;li&gt;Every action has consequences. I weigh them and know how to undo the change before I ship it.&lt;/li&gt;
&lt;li&gt;The little work I do each day is what matters. Hype does not change that.&lt;/li&gt;
&lt;li&gt;Protect my energy. Do not chase the volume.&lt;/li&gt;
&lt;li&gt;When there is so much to do that I do nothing, I pick the smallest next piece and finish it.&lt;/li&gt;
&lt;li&gt;Hyped code carries fear and desperation. Code I understand carries good feelings, and those take time.&lt;/li&gt;
&lt;li&gt;Let AI write the code, and stay close behind it.&lt;/li&gt;
&lt;li&gt;Understand the people first. Then write. Then stop and check the output against what I meant.&lt;/li&gt;
&lt;li&gt;Build checks that make the work stop and ascertain, like the ledger check.&lt;/li&gt;
&lt;li&gt;Name the failure mode when I notice it, and apply its remedy.&lt;/li&gt;
&lt;/ol&gt;




&lt;p&gt;Originally published on &lt;a href="https://miguel-shinyenyi.github.io/miguel-site/philosophy/stay-close-behind-the-code/" rel="noopener noreferrer"&gt;my site&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>philosophy</category>
      <category>ai</category>
      <category>engineering</category>
      <category>java</category>
    </item>
    <item>
      <title>My First Agentic System Is a Folder of Files</title>
      <dc:creator>Miguel Shinyenyi</dc:creator>
      <pubDate>Mon, 26 Oct 2026 11:11:00 +0000</pubDate>
      <link>https://dev.to/miguel_shinyenyi_e2291c8c/my-first-agentic-system-is-a-folder-of-files-gj4</link>
      <guid>https://dev.to/miguel_shinyenyi_e2291c8c/my-first-agentic-system-is-a-folder-of-files-gj4</guid>
      <description>&lt;h2&gt;
  
  
  What it is
&lt;/h2&gt;

&lt;p&gt;The UMWAYI hub is a git repository. It started on 2026-09-16 and has 72 commits. It holds no application code. It holds markdown files: a master context, a journal, a backlog, one file per project, and the content of my website.&lt;/p&gt;

&lt;p&gt;I call it my first agentic system. Here is what I mean. An AI agent reads these files before it does any work. It uses tools to read other repositories, run builds and write files. I read what it hands back and apply it. The files are its memory, its instructions and its record.&lt;/p&gt;

&lt;p&gt;It is not autonomous. The agent cannot push to any of my repositories. I do that.&lt;/p&gt;

&lt;h2&gt;
  
  
  What is in the files
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;MASTER_CONTEXT.md&lt;/code&gt; is about 3,100 words. It holds who I am, the method, and the standing principles for how the agent works with me. It also holds 13 rules that each exist because something went wrong once.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;SYNC_LOG.md&lt;/code&gt; has 31 entries. Each one says what a session used as its source, which files it changed, what moved, and how confident the agent is in what it checked.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;backlog.md&lt;/code&gt; holds every open question and pending action across all projects. An item gets marked answered with a date. It is never deleted.&lt;/p&gt;

&lt;p&gt;Each project has its own file under &lt;code&gt;projects/&lt;/code&gt;. Each repository has a &lt;code&gt;CLAUDE.md&lt;/code&gt; that tells a coding agent which files to read first, in what order, and which rules already apply.&lt;/p&gt;

&lt;h2&gt;
  
  
  A rule is added after a failure
&lt;/h2&gt;

&lt;p&gt;I do not write rules in advance. I add one after something specific breaks. Four examples:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;On 2026-09-20 a session was dated 09-19 because the agent inferred the date from the last entry. The fix was a rule: confirm the actual date before dating anything.&lt;/li&gt;
&lt;li&gt;On 2026-09-22 long files printed into the chat came through cut off. The rule: write long documents to a file and send the file.&lt;/li&gt;
&lt;li&gt;On 2026-10-09 a replacement project page came back with no front matter. The site build rejected it, and two articles stayed offline until I restored it. The rule: run the build with the file in place, and keep the live front matter.&lt;/li&gt;
&lt;li&gt;On 2026-10-19 the file for the Routine Machine project went into the website's folder instead of the hub's. The public page then held text meant only for the hub. We found it five days later, on 2026-10-26. The rule: name the destination again with every handover, and check where it landed.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The fourth one shows the limit. The rule did not exist yet, so nothing stopped it. A written rule closes one kind of failure after the failure has happened.&lt;/p&gt;

&lt;h2&gt;
  
  
  How it reaches the other projects
&lt;/h2&gt;

&lt;p&gt;The hub does not stay in its own folder.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The website reads from it. The &lt;code&gt;miguel-site&lt;/code&gt; repository clones the hub's &lt;code&gt;site/&lt;/code&gt; folder at build time. A push that touches &lt;code&gt;site/&lt;/code&gt; rebuilds the site. Writing an article means editing a file here.&lt;/li&gt;
&lt;li&gt;Routine Machine reads from it. Its backend checks the hub every 15 minutes. A journal file with today's date counts as journaling done. A new file under &lt;code&gt;site/philosophy/&lt;/code&gt; or &lt;code&gt;site/tech/&lt;/code&gt; counts as writing done. A &lt;code&gt;Current book:&lt;/code&gt; line feeds the reading tracker. Two repositories now depend on one line of text, so the rule says the template and the code that reads it change together.&lt;/li&gt;
&lt;li&gt;Each of my three code repositories carries a &lt;code&gt;CLAUDE.md&lt;/code&gt;. Each one copies the same short section from two hub files: one on understanding AI output before you keep it, and one with 111 backend concerns, each answered applies, not applicable or deferred. A copy can drift from the hub, so the section links back to the files.&lt;/li&gt;
&lt;li&gt;Open source work follows a process written in the hub. It says I read the live thread first, check open pull requests, and post and open them myself.&lt;/li&gt;
&lt;li&gt;The settlement engine restudy, the career notes and the application plans each have a file. The agent reads only the file for the project it is touching.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Because of this, a rule written once in the hub can reach every repository. It gets there only when someone copies it into that repository's &lt;code&gt;CLAUDE.md&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Where it is weak
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;A file works only if it is read. I cannot see the agent read it. I can only see what it produces.&lt;/li&gt;
&lt;li&gt;Status files go stale. The website plan and the settlement engine file both lagged the real work for days. I found out when I pointed at them.&lt;/li&gt;
&lt;li&gt;The hub is public. Anything private has to go in the encrypted journal, and I have to remember that each time.&lt;/li&gt;
&lt;li&gt;Rules multiply. Thirteen caught-mistake rules are readable. Fifty would not be.&lt;/li&gt;
&lt;li&gt;Nothing checks the rules automatically, except where a build or a test happens to cover one.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  What I took from it
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;Put the agent's memory in plain files you can read, edit and diff.&lt;/li&gt;
&lt;li&gt;Add a rule after a failure, and write down what failed. The reason keeps the rule from being pruned later.&lt;/li&gt;
&lt;li&gt;Tell the agent what to read first, in order, and keep the list short.&lt;/li&gt;
&lt;li&gt;Check where every handover landed. A file in the wrong folder looks the same as a file in the right one.&lt;/li&gt;
&lt;li&gt;A shared set of files links your projects. Say which parts of each project depend on them.&lt;/li&gt;
&lt;/ol&gt;




&lt;p&gt;Originally published on &lt;a href="https://miguel-shinyenyi.github.io/miguel-site/tech/my-first-agentic-system-is-a-folder/" rel="noopener noreferrer"&gt;my site&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>documentation</category>
      <category>engineering</category>
      <category>claudecode</category>
    </item>
    <item>
      <title>You Cannot Stop What Arrives</title>
      <dc:creator>Miguel Shinyenyi</dc:creator>
      <pubDate>Thu, 15 Oct 2026 01:51:52 +0000</pubDate>
      <link>https://dev.to/miguel_shinyenyi_e2291c8c/you-cannot-stop-what-arrives-co8</link>
      <guid>https://dev.to/miguel_shinyenyi_e2291c8c/you-cannot-stop-what-arrives-co8</guid>
      <description>&lt;h2&gt;
  
  
  What I notice
&lt;/h2&gt;

&lt;p&gt;I cannot stop my thoughts. Try it yourself. Set a timer for thirty seconds and think of nothing. A thought will arrive before you pick it. This is my own observation. I have not checked the research on it.&lt;/p&gt;

&lt;p&gt;Some thoughts arrive with weight. One kind is a standard I did not choose. It asks me to be someone before I have done anything. I cannot meet that kind by working, because it never says what finished looks like.&lt;/p&gt;

&lt;p&gt;This piece started from a line in the Marvel series VisionQuest, about holding someone's memories without their feelings. I have not tried to explain the show. I took the line as a place to start thinking.&lt;/p&gt;

&lt;h2&gt;
  
  
  Three answers to an arrival
&lt;/h2&gt;

&lt;p&gt;I see three ways to answer a thought that weighs too much.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Act on it at once, as if it were an order.&lt;/li&gt;
&lt;li&gt;Shrink so the test never comes. If I never try, I cannot fall short.&lt;/li&gt;
&lt;li&gt;Record what is true, decide what I can, and leave the rest marked as unknown.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The second answer is the one I want to look at. It feels like relief. It also removes the one thing that would tell me whether the weight was real.&lt;/p&gt;

&lt;h2&gt;
  
  
  The same shape in a settlement engine
&lt;/h2&gt;

&lt;p&gt;My settlement engine cannot choose what arrives either. A payment gateway times out. Postgres deadlocks two transactions against each other. Neither event waits for permission. What I control is the state the engine writes next.&lt;/p&gt;

&lt;p&gt;Here is the first decision, trimmed from &lt;code&gt;SettlementService.createSettlement&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;gatewayResult&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;externalSettlementGateway&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;execute&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;executionRequest&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt; &lt;span class="k"&gt;catch&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;Exception&lt;/span&gt; &lt;span class="n"&gt;gatewayFailure&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;gatewayResult&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;GatewayResult&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;SettlementOutcome&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;UNKNOWN&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;finalizeWithRetry&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;executionRequest&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;settlementId&lt;/span&gt;&lt;span class="o"&gt;(),&lt;/span&gt; &lt;span class="n"&gt;gatewayResult&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A timeout means the engine does not know whether the gateway processed the payment. The code says so. It writes UNKNOWN, not CONFIRMED and not FAILED. The comment in the file gives the reason: leaving the settlement PENDING would leave its idempotency key IN_PROGRESS, and every retry with that key would get a 409 with no way to resolve it.&lt;/p&gt;

&lt;p&gt;Here is the second decision, trimmed from &lt;code&gt;finalizeWithRetry&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;attempt&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt; &lt;span class="n"&gt;attempt&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;=&lt;/span&gt; &lt;span class="no"&gt;MAX_FINALIZE_ATTEMPTS&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt; &lt;span class="n"&gt;attempt&lt;/span&gt;&lt;span class="o"&gt;++)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;settlementTransactions&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;finalizeSettlement&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;settlementId&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;gatewayResult&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt; &lt;span class="k"&gt;catch&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;TransientDataAccessException&lt;/span&gt; &lt;span class="n"&gt;transientFailure&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;attempt&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="no"&gt;MAX_FINALIZE_ATTEMPTS&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;finalizeAsUnknownAfterExhaustingRetries&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;settlementId&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;transientFailure&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
        &lt;span class="o"&gt;}&lt;/span&gt;
        &lt;span class="n"&gt;meterRegistry&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;counter&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"settlement.finalize.retries"&lt;/span&gt;&lt;span class="o"&gt;).&lt;/span&gt;&lt;span class="na"&gt;increment&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
        &lt;span class="n"&gt;sleepBriefly&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;attempt&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The last branch is the part that matters. A comment above it says the Phase 9 load test found a bug. When the five attempts ran out with no fallback, the settlement stayed PENDING and its key stayed IN_PROGRESS forever. The failure was not the deadlock. Deadlocks were expected and retried. The failure was that the engine reached a point where it made no decision, and a state with no decision never ends.&lt;/p&gt;

&lt;p&gt;The fix gave the engine a second budget of five attempts that writes UNKNOWN. UNKNOWN is a smaller claim than CONFIRMED. It is also true, and a later reconciliation can resolve it.&lt;/p&gt;

&lt;h2&gt;
  
  
  What I take from the comparison
&lt;/h2&gt;

&lt;p&gt;I do not need to claim greatness, and I do not need to claim failure. Both are large claims, and the evidence for either does not exist yet. The smaller true claim is available: here is what I made today. For anything bigger I can write unknown, and let the record settle it later. My journal does the job that reconciliation does for the engine.&lt;/p&gt;

&lt;p&gt;The stall is the bug. Shrinking so the test never comes is the PENDING state with the key stuck. It looks like safety. It blocks every later attempt.&lt;/p&gt;

&lt;h2&gt;
  
  
  Where the comparison stops
&lt;/h2&gt;

&lt;p&gt;A person is not a service. Three differences matter.&lt;/p&gt;

&lt;p&gt;The engine stops after ten attempts. A person should not cap attempts at ten.&lt;/p&gt;

&lt;p&gt;The engine's UNKNOWN resolves against an outside system that holds the answer. A record of my own work does not hold the answer to my worth. It only holds what I did.&lt;/p&gt;

&lt;p&gt;The engine decides in milliseconds. This decision takes years, and I may get it wrong in both directions. The feeling that I could do great things is a feeling, not evidence. It may be potential. It may be the weight of an expectation. I cannot tell which from inside.&lt;/p&gt;

&lt;h2&gt;
  
  
  What I do not know
&lt;/h2&gt;

&lt;p&gt;I do not know how common the shrinking answer is. I am drawing on my own experience, not on data.&lt;/p&gt;

&lt;p&gt;I read only &lt;code&gt;createSettlement&lt;/code&gt; and &lt;code&gt;finalizeWithRetry&lt;/code&gt; for this piece. I am still restudying the rest of the retry path, so I make no claim about how it behaves under load beyond what the code comments say.&lt;/p&gt;

&lt;h2&gt;
  
  
  What I took from it
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;I cannot stop what arrives. I can choose the state I write next.&lt;/li&gt;
&lt;li&gt;A state that never ends is worse than an honest "unknown".&lt;/li&gt;
&lt;li&gt;Make the next claim small enough to be true: what I made today.&lt;/li&gt;
&lt;li&gt;Keep the record. It settles questions that a feeling at 4 in the morning cannot.&lt;/li&gt;
&lt;/ol&gt;




&lt;p&gt;Originally published on &lt;a href="https://miguel-shinyenyi.github.io/miguel-site/philosophy/you-cannot-stop-what-arrives/" rel="noopener noreferrer"&gt;my site&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>philosophy</category>
      <category>systemsthinking</category>
      <category>java</category>
      <category>visionquest</category>
    </item>
    <item>
      <title>A Convenience Is Hard to Give Back</title>
      <dc:creator>Miguel Shinyenyi</dc:creator>
      <pubDate>Wed, 14 Oct 2026 15:18:31 +0000</pubDate>
      <link>https://dev.to/miguel_shinyenyi_e2291c8c/a-convenience-is-hard-to-give-back-1ico</link>
      <guid>https://dev.to/miguel_shinyenyi_e2291c8c/a-convenience-is-hard-to-give-back-1ico</guid>
      <description>&lt;h2&gt;
  
  
  The claim, as I understand it
&lt;/h2&gt;

&lt;p&gt;This is my understanding of the "luxury trap" passage in Sapiens. It is not a checked account&lt;br&gt;
of the text.&lt;/p&gt;

&lt;p&gt;As I read it, farming was not given up because each change was small. A bit more grain, a bit&lt;br&gt;
more settling, spread over many generations. By the time the cost showed, nobody remembered&lt;br&gt;
another way to live. The extra food had already become the number people lived on.&lt;/p&gt;

&lt;p&gt;My own observation, not the book's: the same thing happens now. A convenience arrives, it&lt;br&gt;
becomes normal, and then it brings work of its own. Email saved time. It also made people&lt;br&gt;
answer faster, and many of us now feel behind on it all day.&lt;/p&gt;
&lt;h2&gt;
  
  
  Three parts, as I see them
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;Each step is small and it helps. Nobody argues against it.&lt;/li&gt;
&lt;li&gt;The step becomes normal, and other things get built on it.&lt;/li&gt;
&lt;li&gt;Going back now costs more than staying, so it does not happen.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;My earlier piece on the farming chapter asked what a measure counts and what it leaves out. This one&lt;br&gt;
asks something else: why nobody steps back once the cost is visible.&lt;/p&gt;
&lt;h2&gt;
  
  
  The same shape in code
&lt;/h2&gt;

&lt;p&gt;A payment call sometimes times out. Adding a retry is one small step. Callers stop handling&lt;br&gt;
timeouts and the code gets shorter. This is a toy, run on one machine, with the reply lost&lt;br&gt;
exactly once:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="kd"&gt;static&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="nf"&gt;withRetry&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;Supplier&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;call&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;attempts&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt; &lt;span class="o"&gt;;&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="o"&gt;++)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;call&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;get&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
        &lt;span class="o"&gt;}&lt;/span&gt; &lt;span class="k"&gt;catch&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;TimeoutException&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="n"&gt;attempts&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
        &lt;span class="o"&gt;}&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;

&lt;span class="nc"&gt;Gateway&lt;/span&gt; &lt;span class="n"&gt;plain&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Gateway&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
&lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;r1&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;withRetry&lt;/span&gt;&lt;span class="o"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;plain&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;charge&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;5000&lt;/span&gt;&lt;span class="o"&gt;),&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
&lt;span class="c1"&gt;// Retry, no key:   receipt=R2 charges=2&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The first call moved the money and lost the reply. The retry moved it again. The customer was&lt;br&gt;
charged twice, and the convenience caused it.&lt;/p&gt;

&lt;p&gt;The fix is a key made once and sent on every attempt. The server remembers it:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="nc"&gt;Gateway&lt;/span&gt; &lt;span class="n"&gt;keyed&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Gateway&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
&lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;key&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;UUID&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;randomUUID&lt;/span&gt;&lt;span class="o"&gt;().&lt;/span&gt;&lt;span class="na"&gt;toString&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;   &lt;span class="c1"&gt;// made once, reused on every retry&lt;/span&gt;
&lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;r2&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;withRetry&lt;/span&gt;&lt;span class="o"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;keyed&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;charge&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;key&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;5000&lt;/span&gt;&lt;span class="o"&gt;),&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
&lt;span class="c1"&gt;// Retry, with key: receipt=R1 charges=1&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That fixes it, and it adds work. The server needs a place to store keys. Something has to&lt;br&gt;
decide how long a key lives. A second request can arrive while the first is still running, so&lt;br&gt;
a key needs a state. In the settlement engine I built, the design has those pieces: keys with&lt;br&gt;
an in-progress and a completed state, and a scheduled sweep for the case where a process&lt;br&gt;
crashed before it finished, which would leave a key stuck in progress. I am describing the design as it stands, not the order I built&lt;br&gt;
it in.&lt;/p&gt;

&lt;p&gt;Now take the retry out. Every caller has stopped handling timeouts. Every server is built to&lt;br&gt;
expect repeats. Removing one line is not a one-line change anymore. That is the third part&lt;br&gt;
above, in a place I can read.&lt;/p&gt;

&lt;h2&gt;
  
  
  Where the comparison stops
&lt;/h2&gt;

&lt;p&gt;The first farmers could not see where it led. I can see this one. I can read the cost in code&lt;br&gt;
before I add the step, and I can choose.&lt;/p&gt;

&lt;p&gt;That does not make the step reversible. It only lets me price it first. A habit I want to try&lt;br&gt;
before adding any convenience: write down the work I will have to keep doing because of it,&lt;br&gt;
and who will start depending on it.&lt;/p&gt;

&lt;h2&gt;
  
  
  What I do not know
&lt;/h2&gt;

&lt;p&gt;I do not know whether AI tools save me hours, or raise what I expect of myself in the same&lt;br&gt;
hours. That is the luxury trap question, asked of my own week. I have a feeling about it, and&lt;br&gt;
a feeling is not a measure. A test I have not run: log hours and output for two weeks, with&lt;br&gt;
and without the tool, and compare.&lt;/p&gt;

&lt;p&gt;Other limits. I have not checked the chapter's evidence. The email point is my observation.&lt;br&gt;
The retry example is a toy with one lost reply. The link to the settlement engine describes&lt;br&gt;
its design, not a history of how I got there.&lt;/p&gt;

&lt;h2&gt;
  
  
  What I took from it
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;A convenience that helps today can add work you cannot stop doing tomorrow. Look for that
work before you add it.&lt;/li&gt;
&lt;li&gt;Small steps hide the cost. The first one is the cheapest time to price it.&lt;/li&gt;
&lt;li&gt;Seeing the trap does not undo it. Reversing gets harder as other things depend on the step.&lt;/li&gt;
&lt;li&gt;A feeling that a tool saves time is not a measure. Count the hours.&lt;/li&gt;
&lt;/ol&gt;




&lt;p&gt;Originally published on &lt;a href="https://miguel-shinyenyi.github.io/miguel-site/philosophy/a-convenience-is-hard-to-give-back/" rel="noopener noreferrer"&gt;my site&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>sapiens</category>
      <category>systemsthinking</category>
      <category>idempotency</category>
    </item>
    <item>
      <title>More Copies Is Not a Better Life</title>
      <dc:creator>Miguel Shinyenyi</dc:creator>
      <pubDate>Fri, 09 Oct 2026 14:06:05 +0000</pubDate>
      <link>https://dev.to/miguel_shinyenyi_e2291c8c/more-copies-is-not-a-better-life-559c</link>
      <guid>https://dev.to/miguel_shinyenyi_e2291c8c/more-copies-is-not-a-better-life-559c</guid>
      <description>&lt;h2&gt;
  
  
  The claim, as I understand it
&lt;/h2&gt;

&lt;p&gt;This is my understanding of Part 2, Chapter 1 of Sapiens, "History's Biggest Fraud". It is&lt;br&gt;
not a checked account of the text.&lt;/p&gt;

&lt;p&gt;As I read it, the chapter says farming did not make people smarter or their lives easier.&lt;br&gt;
The average farmer worked harder than the average forager and ate a narrower diet. The&lt;br&gt;
chapter blames a few plants: wheat, rice, potatoes. They planned nothing. But the people who&lt;br&gt;
tended them left more descendants, so the habit spread, and the plants now cover far more&lt;br&gt;
ground than before. People settled next to the fields and worked to keep them alive. In the&lt;br&gt;
chapter's framing, the plants domesticated us.&lt;/p&gt;

&lt;p&gt;I can check one part of this outside the book. Researchers compare skeletons from before and&lt;br&gt;
after farming arrived. I found two sources: a 2011 paper on stature and robusticity across the&lt;br&gt;
agricultural transition, and a review titled "Foraging to Farming Transition: Global Health&lt;br&gt;
Impacts, Trends, and Variation". I could not open either. I only confirmed that they exist.&lt;br&gt;
Both titles point at health costs, and the second points at variation between regions. Treat&lt;br&gt;
that as a lead, not a finding.&lt;/p&gt;

&lt;h2&gt;
  
  
  Two numbers that moved apart
&lt;/h2&gt;

&lt;p&gt;The chapter's point, as I take it: evolution measures success in copies of DNA. More people&lt;br&gt;
means more copies. By that measure farming won, for the plants and for our species. The same&lt;br&gt;
measure has no column for how any one person's life went.&lt;/p&gt;

&lt;p&gt;Farming kept more people alive under worse conditions. Both halves of that sentence are true&lt;br&gt;
at once, because they count different things. One counts how many. The other counts how well.&lt;/p&gt;

&lt;p&gt;The chapter also warns against judging thousands of years by how we live now. Today's&lt;br&gt;
security and wealth sit on what farming made possible. A bad deal for the average farmer and&lt;br&gt;
a base for later life can both be true.&lt;/p&gt;

&lt;h2&gt;
  
  
  Where my company comparison holds
&lt;/h2&gt;

&lt;p&gt;I compared it to a company. A company's goal is to make money, not to keep its employees&lt;br&gt;
happy. Revenue can rise while happiness falls, because happiness is not in the number.&lt;/p&gt;

&lt;p&gt;That is the same structure: one measure, and people it does not count.&lt;/p&gt;

&lt;h2&gt;
  
  
  Where it stops holding
&lt;/h2&gt;

&lt;p&gt;Wheat cannot notice anything. A company has people in it who can notice the gap and close it.&lt;br&gt;
Some leaders treat employee happiness as a way to keep staff and raise output. Some treat it&lt;br&gt;
as a goal. Either way, a person decided. Evolution has nobody to decide.&lt;/p&gt;

&lt;p&gt;So the version of the comparison I trust is smaller. A system judged by one number drifts away&lt;br&gt;
from the welfare of the people inside it, unless someone ties the two together on purpose.&lt;/p&gt;

&lt;p&gt;A company whose growth and employee welfare both rise today has not shown that anyone tied&lt;br&gt;
them. They may be moving together for now. A test: when the number is threatened, what gets&lt;br&gt;
cut first? If employee welfare goes first, the tie was never there. I have not applied this&lt;br&gt;
test to any company yet.&lt;/p&gt;

&lt;h2&gt;
  
  
  What I am not sure about
&lt;/h2&gt;

&lt;p&gt;I have not read the chapter's figures on hours worked or diet. "Worked harder, ate worse" is&lt;br&gt;
the chapter's claim to me, not one I checked. The skeleton evidence appears to vary by region,&lt;br&gt;
going by the titles alone.&lt;/p&gt;

&lt;p&gt;Farming also gave us things foragers did not have: surplus, people who could stop growing&lt;br&gt;
food, writing, cities. "Fraud" describes one axis, the average person's daily life. I do not&lt;br&gt;
know how to weigh it against the others, and I am not sure the chapter claims to.&lt;/p&gt;

&lt;h2&gt;
  
  
  What I took from it
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;A system can win by its own measure while the people inside it lose by theirs. Ask what the
number counts and what it leaves out.&lt;/li&gt;
&lt;li&gt;More is not better. Copies, revenue and output all count quantity.&lt;/li&gt;
&lt;li&gt;A comparison is useful until it stops fitting. Say where it stops. Here: wheat cannot
choose, a company can.&lt;/li&gt;
&lt;li&gt;A measure lines up with people's welfare on purpose only if something protects the link when
protecting it costs. What gets cut first shows which one the system serves.&lt;/li&gt;
&lt;/ol&gt;




&lt;p&gt;Originally published on &lt;a href="https://miguel-shinyenyi.github.io/miguel-site/philosophy/more-copies-is-not-a-better-life/" rel="noopener noreferrer"&gt;my site&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>sapiens</category>
      <category>incentives</category>
      <category>systemsthinking</category>
    </item>
    <item>
      <title>What the Reconciler Can't See</title>
      <dc:creator>Miguel Shinyenyi</dc:creator>
      <pubDate>Fri, 09 Oct 2026 14:05:32 +0000</pubDate>
      <link>https://dev.to/miguel_shinyenyi_e2291c8c/what-the-reconciler-cant-see-469g</link>
      <guid>https://dev.to/miguel_shinyenyi_e2291c8c/what-the-reconciler-cant-see-469g</guid>
      <description>&lt;h2&gt;
  
  
  Explain it cold, then check
&lt;/h2&gt;

&lt;p&gt;Same method as before: explain the subsystem from memory, then check it against the code.&lt;/p&gt;

&lt;p&gt;My cold answer was this. Reconciliation is the last resort. When the system cannot settle a&lt;br&gt;
payment on its own, it marks the payment UNKNOWN and pushes it to a place where someone is&lt;br&gt;
alerted. That person looks, finds what went wrong, and either records an answer or edits the&lt;br&gt;
data.&lt;/p&gt;

&lt;p&gt;The code disagreed with that in three places. It also showed me a fourth problem I had not&lt;br&gt;
thought to ask about.&lt;/p&gt;
&lt;h2&gt;
  
  
  Unknown and conflicting are different problems
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;ReconciliationService.runOnce&lt;/code&gt; loads every settlement that has an external reference and&lt;br&gt;
compares each one to the external system's own record. This is what it does with one:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;look up the external record
  none, under 5 min   -&amp;gt; wait
  none, over 5 min    -&amp;gt; mismatch
  amount or currency
    differs           -&amp;gt; mismatch
  settlement UNKNOWN  -&amp;gt; adopt external
  both CONFIRMED or
    both FAILED       -&amp;gt; nothing
  anything else       -&amp;gt; mismatch
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I had filed UNKNOWN under "needs a person". It does not. If the settlement is UNKNOWN and the&lt;br&gt;
external record agrees on amount and currency, the engine settles it by itself, using the same&lt;br&gt;
method the original request would have used:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="nc"&gt;SettlementOutcome&lt;/span&gt; &lt;span class="n"&gt;resolvedOutcome&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;externalRecord&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;status&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="nc"&gt;ExternalStatus&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;CONFIRMED&lt;/span&gt;
        &lt;span class="o"&gt;?&lt;/span&gt; &lt;span class="nc"&gt;SettlementOutcome&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;CONFIRMED&lt;/span&gt; &lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;SettlementOutcome&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;FAILED&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="n"&gt;settlementTransactions&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;finalizeSettlement&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;settlement&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getId&lt;/span&gt;&lt;span class="o"&gt;(),&lt;/span&gt;
        &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;GatewayResult&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;resolvedOutcome&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;settlement&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getExternalRef&lt;/span&gt;&lt;span class="o"&gt;()));&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A person is needed only when the two sides contradict each other. The project's own doc gives&lt;br&gt;
the reason: if a settlement is already CONFIRMED and the external system now disputes it, money&lt;br&gt;
may have moved, and only a person can judge what to do. So the rule is: evidence that fills a&lt;br&gt;
gap gets applied automatically. Evidence that conflicts waits for a person.&lt;/p&gt;
&lt;h2&gt;
  
  
  It runs on a timer, not on failure
&lt;/h2&gt;

&lt;p&gt;A scheduler calls &lt;code&gt;runOnce&lt;/code&gt; every 60 seconds by default, whether or not anything went wrong.&lt;br&gt;
Each pass loads every settlement that has ever had a reference, with no date window and no&lt;br&gt;
paging, and asks the external side about each one. That is fine at this size. At real volume,&lt;br&gt;
the same query is also the cost.&lt;/p&gt;
&lt;h2&gt;
  
  
  The query decides what it can see
&lt;/h2&gt;

&lt;p&gt;The candidate query is &lt;code&gt;findByExternalRefIsNotNull()&lt;/code&gt;. A settlement only gets a reference&lt;br&gt;
inside &lt;code&gt;finalizeSettlement&lt;/code&gt;, and only when the gateway returns one:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;gatewayResult&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;externalRef&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;settlement&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;setExternalRef&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;gatewayResult&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;externalRef&lt;/span&gt;&lt;span class="o"&gt;());&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Three paths end in UNKNOWN with no reference:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;The gateway call throws. &lt;code&gt;SettlementService&lt;/code&gt; builds &lt;code&gt;new GatewayResult(UNKNOWN, null)&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;The finalize retry budget runs out. The fallback uses the same null.&lt;/li&gt;
&lt;li&gt;The stale-pending sweep finalizes an orphaned PENDING settlement as UNKNOWN, also with
null.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;None of these can reach the auto-resolve step, because reconciliation never loads them. They&lt;br&gt;
do not open a mismatch either. They stay UNKNOWN.&lt;/p&gt;

&lt;p&gt;The case that worries me most is the second failure type from the project's design doc: the&lt;br&gt;
external system processed the payment, and the response was lost. The money moved. The engine&lt;br&gt;
never learned the reference. The project's own open-questions list names this and two fixes:&lt;br&gt;
ask the external system what it received for this settlement, or match on amount, date and&lt;br&gt;
account. Neither is built. I checked the code instead of trusting the doc, and the doc was&lt;br&gt;
right.&lt;/p&gt;

&lt;h2&gt;
  
  
  Nobody is told
&lt;/h2&gt;

&lt;p&gt;I said the person gets alerted. In the code, a new mismatch is published as the event&lt;br&gt;
&lt;code&gt;reconciliation.mismatch_found&lt;/code&gt;. Nothing consumes it. The Kafka doc says "No consumer yet". The&lt;br&gt;
Prometheus rules cover three things: the backend being down, the ML service being down, and a&lt;br&gt;
spike in failed settlements. None covers mismatches.&lt;/p&gt;

&lt;p&gt;So a mismatch waits until someone opens the reconciliation page. A record in a table&lt;br&gt;
guarantees a person can find the problem. It does not guarantee a person will.&lt;/p&gt;

&lt;h2&gt;
  
  
  Recording a decision is not making it happen
&lt;/h2&gt;

&lt;p&gt;The resolve endpoint takes a reason, marks the mismatch resolved, and writes an audit row and&lt;br&gt;
an event. Its own description says it does not change the settlement or the ledger.&lt;/p&gt;

&lt;p&gt;For ledger mismatches the docs say what follows: if the data still disagrees, the next read of&lt;br&gt;
that account opens a new mismatch. Reading &lt;code&gt;flagMismatch&lt;/code&gt;, the same should hold for settlement&lt;br&gt;
mismatches, since it only skips a settlement that already has an open row. I read that. I have&lt;br&gt;
not run it.&lt;/p&gt;

&lt;p&gt;No endpoint corrects data. &lt;code&gt;REVERSED&lt;/code&gt; exists in the state machine and is reachable from&lt;br&gt;
CONFIRMED, but nothing in the code ever moves a settlement there. Today the correction is a&lt;br&gt;
person editing the database by hand. That edit skips the state machine, the ledger entries and&lt;br&gt;
the outbox event, because all three live in application code.&lt;/p&gt;

&lt;p&gt;My first answer was "a person edits it". Keeping the decision with a person is right. The&lt;br&gt;
open question is who carries it out. Either the person edits rows directly, or the person&lt;br&gt;
decides and the engine executes it through the same paths as every other money movement. I&lt;br&gt;
have not decided between them.&lt;/p&gt;

&lt;h2&gt;
  
  
  What I took from it
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;Evidence that fills a gap can be applied automatically. Evidence that conflicts needs a
person.&lt;/li&gt;
&lt;li&gt;A checker sees only what its query returns. Ask what the query cannot return.&lt;/li&gt;
&lt;li&gt;A record in a table is not an alert. Someone has to be told.&lt;/li&gt;
&lt;li&gt;Recording a decision does not carry it out. Decide who does.&lt;/li&gt;
&lt;/ol&gt;




&lt;p&gt;Originally published on &lt;a href="https://miguel-shinyenyi.github.io/miguel-site/tech/what-the-reconciler-cant-see/" rel="noopener noreferrer"&gt;my site&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>springboot</category>
      <category>postgres</category>
      <category>reconciliation</category>
      <category>kafka</category>
    </item>
    <item>
      <title>What Becomes True When Both Stay</title>
      <dc:creator>Miguel Shinyenyi</dc:creator>
      <pubDate>Tue, 29 Sep 2026 22:54:22 +0000</pubDate>
      <link>https://dev.to/miguel_shinyenyi_e2291c8c/what-becomes-true-when-both-stay-11k2</link>
      <guid>https://dev.to/miguel_shinyenyi_e2291c8c/what-becomes-true-when-both-stay-11k2</guid>
      <description>&lt;h2&gt;
  
  
  The curtain of silence
&lt;/h2&gt;

&lt;p&gt;Sapiens describes the evidence for prehistoric life as a Rorschach test. A burial site with&lt;br&gt;
ornaments on a skeleton might mean hierarchy. It might mean something else entirely. A&lt;br&gt;
fracture on an ancient bone might mean violence. It might not. The book calls this its&lt;br&gt;
Curtain of Silence, evidence thin enough that even careful scholarship can't get a clean&lt;br&gt;
answer through it. Scholars keep asking anyway, because the past still shaped what came&lt;br&gt;
after it, but the honest version of that inquiry holds its answers loosely.&lt;/p&gt;

&lt;p&gt;That's a claim about archaeology. It turned out to be useful somewhere closer to home.&lt;/p&gt;
&lt;h2&gt;
  
  
  Two truths instead of one
&lt;/h2&gt;

&lt;p&gt;Dialectical thinking, how my mind works?,&lt;br&gt;
it generates a position and its counter-argument at the same time. Useful when pointed&lt;br&gt;
outward. Corrosive when pointed inward, because the counter-argument doesn't sit next to the&lt;br&gt;
first position, it tries to erase it. Grateful for the past, but it cost me something real,&lt;br&gt;
failing a job interview among the costs. Forgiving someone, but not reconciled with them.&lt;br&gt;
The old move was picking one of those as the real feeling and discarding the other as noise.&lt;/p&gt;

&lt;p&gt;The question that actually helps isn't which one is true. Both are. The question is what&lt;br&gt;
becomes true if I stop forcing a choice between them.&lt;/p&gt;
&lt;h2&gt;
  
  
  A system that already does this
&lt;/h2&gt;

&lt;p&gt;The settlement engine I built has a state called&lt;br&gt;
&lt;code&gt;UNKNOWN&lt;/code&gt;. It's not a bug, it's a deliberate third option, used when a payment might have&lt;br&gt;
gone through or might not have, and the system genuinely doesn't have enough information yet&lt;br&gt;
to say which.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Reused across three different situations: a real gateway failure,&lt;/span&gt;
&lt;span class="c1"&gt;// exhausted retries after a database deadlock, and a hard crash that&lt;/span&gt;
&lt;span class="c1"&gt;// left a settlement stuck with no way to confirm what happened.&lt;/span&gt;
&lt;span class="n"&gt;settlementTransactions&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;finalizeSettlement&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;settlementId&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
        &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;GatewayResult&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;SettlementOutcome&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;UNKNOWN&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="o"&gt;));&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The tempting design is to force an answer immediately: retry until you get a clean yes or no,&lt;br&gt;
because "unknown" feels like a failure to decide. The actual design holds &lt;code&gt;UNKNOWN&lt;/code&gt; as a&lt;br&gt;
first-class state, moves on, and lets a separate reconciliation process resolve it later,&lt;br&gt;
once there's real information to resolve it with. Forcing a premature CONFIRMED or FAILED&lt;br&gt;
would be lying to the rest of the system, papering over uncertainty that was still genuinely&lt;br&gt;
open. The honest version of "I don't know yet" turns out to be more useful than a fast, fake&lt;br&gt;
certainty. That's the same shape as forgiving without reconciling. Not every open state needs&lt;br&gt;
collapsing into a resolved one on a deadline. Some of them get resolved later, correctly,&lt;br&gt;
once there's enough to resolve them with. Some of them are just allowed to be two things at&lt;br&gt;
once, permanently, the way gratitude and grief can both be true about the same period without&lt;br&gt;
either one cancelling the other.&lt;/p&gt;
&lt;h2&gt;
  
  
  Where this gets tested, not just described
&lt;/h2&gt;

&lt;p&gt;I've also been carrying a specific belief:&lt;br&gt;
that my anxiety comes from a need to control everything. It's a real, documented idea in&lt;br&gt;
general, intolerance of uncertainty, anxiety tracking unpredictability rather than actual&lt;br&gt;
danger, controlling behavior as an attempt to shrink that unpredictability back down. But a&lt;br&gt;
documented general pattern isn't the same as a verified account of one specific person, and&lt;br&gt;
right now I don't have an instance attached to it, just the label.&lt;/p&gt;

&lt;p&gt;There's a code parallel here too, and it's not a flattering one. The same idempotency work&lt;br&gt;
this week turned up two concurrency races, both caused by the system trying to guarantee&lt;br&gt;
too much certainty upfront.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Two requests, same key, same instant.

Option A: lock everything before
either proceeds. Force certainty
immediately.

Option B: let both proceed. The
database's unique constraint decides
who wins. The loser recovers by
reading the winner's result.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The actual code takes option B. Locking everything upfront to force immediate certainty is&lt;br&gt;
exactly what produces a deadlock later, two transactions each holding what the other one&lt;br&gt;
wants, both stuck, because the system tried to control too much of the outcome up front&lt;br&gt;
instead of accepting a controlled version of not-knowing-yet and resolving it after the&lt;br&gt;
fact. The fix that shipped this week for the crash-recovery gap follows the same shape: not&lt;br&gt;
tighter control at the moment of failure, a sweep that runs later, accepts the outcome was&lt;br&gt;
genuinely unknown for a while, and resolves it once enough time has passed to trust the&lt;br&gt;
answer.&lt;/p&gt;

&lt;p&gt;I don't know yet whether "addiction to control" is actually what's driving the anxiety, or&lt;br&gt;
just the label that was closest at hand when I needed one. That's not resolved in this&lt;br&gt;
piece, on purpose. If forcing a system to decide before it has enough information produces a&lt;br&gt;
deadlock, forcing a belief about myself into a tidy answer before I've actually tested it&lt;br&gt;
probably isn't any more reliable. The honest state to hold it in, for now, is &lt;code&gt;UNKNOWN&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  What I took from it
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;Two things can both be true about the same period. Stop asking which one is real.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;UNKNOWN&lt;/code&gt; is an honest state. A fast, fake certainty is worse than a slow, correct answer.&lt;/li&gt;
&lt;li&gt;Forcing certainty upfront is what caused the deadlocks. That applies to beliefs about
myself too.&lt;/li&gt;
&lt;li&gt;"My anxiety comes from control" stays a hypothesis until a real instance tests it.&lt;/li&gt;
&lt;/ol&gt;




&lt;p&gt;Originally published on &lt;a href="https://miguel-shinyenyi.github.io/miguel-site/philosophy/what-becomes-true-when-both-stay/" rel="noopener noreferrer"&gt;my site&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>sapiens</category>
      <category>selfobservation</category>
      <category>concurrency</category>
    </item>
  </channel>
</rss>
