<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0"><channel><title><![CDATA[LifeWiki Lab]]></title><description><![CDATA[LifeWiki Lab documents the real-world engineering of AI agents with persistent memory, verifiable learning, local language models, and reusable Python architecture.]]></description><link>https://lifewiki-lab.hashnode.dev</link><image><url>https://cdn.hashnode.com/uploads/logos/6ad628f812bb8921f3a79ac9/e6a837c3-c4a2-4d56-a39f-ce90e09a8ce4.png</url><title>LifeWiki Lab</title><link>https://lifewiki-lab.hashnode.dev</link></image><generator>RSS for Node</generator><lastBuildDate>Sun, 25 Oct 2026 14:09:54 GMT</lastBuildDate><atom:link href="https://lifewiki-lab.hashnode.dev/rss.xml" rel="self" type="application/rss+xml"/><language><![CDATA[en]]></language><ttl>60</ttl><item><title><![CDATA[Correct Answers Aren’t Enough: What It Took to Benchmark, Debug, and Archive an AI Baseball Analyst]]></title><description><![CDATA[I built an AI baseball analyst, debugged Claude API failures, and learned why correct facts don't always mean a trustworthy AI answer.]]></description><link>https://lifewiki-lab.hashnode.dev/correct-answers-arent-enough-ai-baseball-analyst</link><guid isPermaLink="true">https://lifewiki-lab.hashnode.dev/correct-answers-arent-enough-ai-baseball-analyst</guid><category><![CDATA[AI]]></category><category><![CDATA[Machine Learning]]></category><category><![CDATA[Python]]></category><category><![CDATA[SQLite]]></category><category><![CDATA[Benchmark]]></category><category><![CDATA[agentic AI]]></category><category><![CDATA[llm]]></category><dc:creator><![CDATA[PeterHuesson]]></dc:creator><pubDate>Wed, 21 Oct 2026 10:17:28 GMT</pubDate><content:encoded><![CDATA[<p><em>From a frozen baseball benchmark and a painful Claude debugging loop to a local artifact ledger for preserving model outputs.</em></p>
<img src="https://cdn.hashnode.com/uploads/covers/6ad628f812bb8921f3a79ac9/e36fef99-7d94-429a-bfd4-c04abeff0d3f.png" alt="LifeWiki Lab article cover: a baseball AI network with benchmark, chart, checklist, and archive panels" style="display:block;margin:0 auto" />

<blockquote>
<p><strong>The experiment:</strong> What does it actually take to trust an AI baseball analyst a little more? Not just a model that sometimes gives the right numbers—but a system that can be benchmarked, debugged, cost-controlled, and audited after the fact.</p>
</blockquote>
<p>In the first LifeWiki Lab entry, I built the foundation: a local memory architecture, a small baseball data pipeline, and the first serious attempt to test whether a model could learn from its mistakes.</p>
<p>This second phase was less romantic.</p>
<p>I already had the baseball tools. I already had a reproducible benchmark. What I needed next was something more uncomfortable: a way to tell the difference between <strong>a correct calculation, a correct answer, a broken provider integration, and a bad evaluation contract</strong>.</p>
<p>That turned out to be the real work.</p>
<h2>Right numbers are not enough</h2>
<p>The first benchmark I froze for LifeWiki Lab was intentionally narrow: eight fixed baseball research questions, a fixed prompt plan, fixed tool outputs, and fixed oracles. The idea was to stop hand-waving and force the project into repeatable conditions.</p>
<p>The first local run used <strong>Qwen3 4B through Ollama</strong>.</p>
<p>At a glance, the results looked promising. The model often repeated the right tool-derived numbers and cited the right evidence. But the stricter rubric told a more interesting story.</p>
<img src="https://cdn.hashnode.com/uploads/covers/6ad628f812bb8921f3a79ac9/42d5fa8b-4908-4174-9fd2-18fbd97adae6.png" alt="Benchmark summary graphic showing 5 scorable answers, facts 4/5, sources 5/5, and overall rubric passes 0/5" style="display:block;margin:0 auto" />

<p><em>Figure 1. The first frozen benchmark already exposed the core problem: correct facts and correct citations did not reliably produce a fully correct answer.</em></p>
<p>Five answers were scorable before the run hit a timeout and the preplanned stop. On those five:</p>
<ul>
<li><p><strong>Facts passed in 4 / 5 cases</strong></p>
</li>
<li><p><strong>Sources passed in 5 / 5 cases</strong></p>
</li>
<li><p><strong>Overall strict-rubric passes were 0 / 5</strong></p>
</li>
</ul>
<p>That does not mean the system was useless. It means the benchmark was doing its job.</p>
<p>The failures were not random. They clustered around:</p>
<ul>
<li><p><strong>time-window mistakes</strong></p>
</li>
<li><p><strong>an unsupported streak claim</strong></p>
</li>
<li><p><strong>strict structured-output mismatches</strong></p>
</li>
</ul>
<p>That is a much more valuable result than a vague sense that the model felt “pretty good.” It told me the project had reached an important threshold: <strong>I could now separate deterministic tool correctness from model explanation quality.</strong></p>
<h2>Then the cloud comparison went sideways</h2>
<p>The next step seemed obvious. If the local model was useful but imperfect, I wanted a controlled replay with a stronger cloud model.</p>
<p>So I built an Anthropic benchmark runner that replays the same frozen plan. No fresh research. No dynamic prompt drift. No quiet changes to the benchmark questions. Just the same stored inputs, the same tool outputs, and a cost check before any API call.</p>
<p>That should have produced a clean model comparison.</p>
<p>Instead, it produced a debugging project.</p>
<p>The first Claude replay stopped at <strong>BR02</strong>, the second benchmark case. Then it happened again. At first, the failure data were barely useful. I had a generic <code>model_error</code>, but not a satisfying explanation of <em>why</em> the job stopped.</p>
<p>That failure forced me to improve the tooling before I could responsibly compare models.</p>
<h2>Why BR02 kept failing</h2>
<p>Once I added single-case reruns, better diagnostics, and safer tracking of stop reasons and token usage, the path became visible.</p>
<img src="https://cdn.hashnode.com/uploads/covers/6ad628f812bb8921f3a79ac9/e409eeec-ee8e-41c1-89c3-cee3d8c31c96.png" alt="Debugging path showing the BR02 stop, max_tokens clue, raised limit to 4096, second rejection, and final parser fix" style="display:block;margin:0 auto" />

<p><em>Figure 2. The debugging path mattered more than the first comparison result. Before I could compare reasoning quality, I had to understand a provider-integration failure.</em></p>
<p>The sequence looked like this:</p>
<ol>
<li><p><strong>The replay stopped at BR02.</strong></p>
</li>
<li><p>The first useful clue showed <code>max_tokens</code> <strong>had been reached</strong>.</p>
</li>
<li><p>I raised the explicit output limit from <strong>1,024 to 4,096 tokens</strong>.</p>
</li>
<li><p>The run still failed.</p>
</li>
<li><p>The real root cause turned out to be structural: the provider returned a valid <code>thinking</code> <strong>block</strong> before the visible text block, and my parser rejected the whole response instead of ignoring the thinking block and extracting the final text.</p>
</li>
</ol>
<p>That distinction matters a lot.</p>
<p>If a benchmark job fails because my software cannot parse a valid response shape, that is <strong>not</strong> the same thing as the model failing to answer a baseball question. An API-shape bug should not be casually interpreted as poor baseball reasoning.</p>
<p>So I changed the parser to:</p>
<ul>
<li><p>ignore supported <code>thinking</code> blocks</p>
</li>
<li><p>extract the visible text blocks in order</p>
</li>
<li><p>keep strict validation for malformed or unknown block types</p>
</li>
<li><p>continue rejecting unsupported content rather than silently guessing</p>
</li>
</ul>
<p>This was not glamorous AI progress. It was infrastructure work. But it made the benchmark more honest.</p>
<h2>Single-case reruns changed the economics</h2>
<p>One of the most practical improvements was also one of the smallest: the ability to rerun <strong>just one failing case</strong>.</p>
<p>That changed how debugging felt.</p>
<img src="https://cdn.hashnode.com/uploads/covers/6ad628f812bb8921f3a79ac9/31aa92f8-49b9-499b-98e0-592aea0d9ed3.png" alt="Cost comparison between an 8-case Sonnet replay and a 1-case Haiku BR02 rerun, plus the observability advantages of rerunning a single failure" style="display:block;margin:0 auto" />

<p><em>Figure 3. Single-case tooling turned an expensive blind replay into a controlled diagnostic loop.</em></p>
<p>With the full Sonnet replay, the benchmark printed an <strong>estimated maximum cost of $0.267476</strong> for eight calls.</p>
<p>For BR02, after the parser fixes, I could validate the path using <strong>Claude Haiku</strong> in single-case mode. One successful evaluable rerun came in at about <strong>$0.0018</strong>, or roughly <strong>0.18 US cents</strong>.</p>
<p>That did not just save money. It improved the whole development loop:</p>
<ul>
<li><p>target only the failing case</p>
</li>
<li><p>record usage and stop reasons precisely</p>
</li>
<li><p>validate fixes cheaply before rerunning a larger benchmark</p>
</li>
</ul>
<p>For plumbing and error-handling work, Haiku was exactly the right tool. Burning larger-model budget before the integration layer is trustworthy would have been wasteful.</p>
<h2>The answer was “incorrect”—but that was not the whole story</h2>
<p>After the parser fix, the BR02 rerun finally produced a stored visible answer that could be evaluated.</p>
<p>The headline result was still <code>incorrect</code>.</p>
<p>But when I inspected the actual answer, the situation was more nuanced.</p>
<p>Haiku gave the right date window. It gave the right baseball counts. It cited the right source evidence. It avoided unsupported historical overreach. It explicitly warned that season completeness had not been independently verified.</p>
<p>The failure came from a machine-readable contract detail: the benchmark oracle expected the <code>coverage.completeness</code> field to equal exactly:</p>
<pre><code class="language-json">"not_independently_verified"
</code></pre>
<p>Haiku wrote a longer but still reasonable formulation:</p>
<pre><code class="language-json">"matching_rows_only; season completeness not independently verified"
</code></pre>
<p>Under the frozen rubric, that is a failure. Under a looser human reading, it is substantively fine.</p>
<p>That is exactly the kind of distinction I wanted the project to expose.</p>
<p>A result labeled <code>incorrect</code> can mean at least three different things:</p>
<ol>
<li><p><strong>the baseball facts were wrong</strong></p>
</li>
<li><p><strong>the interpretation overreached</strong></p>
</li>
<li><p><strong>the model missed a strict structured-output contract even though the answer was semantically reasonable</strong></p>
</li>
</ol>
<p>Those are not the same failure mode, and they should not be treated as if they are.</p>
<h2>I realized I wasn’t keeping the answers</h2>
<p>During this debugging phase I ran into a second, more embarrassing problem.</p>
<p>I had increasingly careful benchmark outputs: statuses, evaluations, costs, hashes, diagnostics.</p>
<p>But I was not always preserving the actual visible answer text.</p>
<p>That might be acceptable for throwaway tests. It is a bad strategy for a system that is supposed to become a research assistant, a blog-drafting assistant, or eventually a supervised social-post generator.</p>
<p>So I added a local <strong>Model Artifact Ledger</strong>.</p>
<img src="https://cdn.hashnode.com/uploads/covers/6ad628f812bb8921f3a79ac9/05deff45-5f05-470d-befb-39133f7d7bd1.png" alt="Artifact ledger diagram showing the model artifact, review and evaluation events, and the boundary between archived output and verified knowledge" style="display:block;margin:0 auto" />

<p><em>Figure 4. The artifact ledger stores what the model actually said without confusing that response with validated facts or long-term memory.</em></p>
<p>The ledger keeps a clean separation between three different things:</p>
<ul>
<li><p><strong>the visible model answer</strong></p>
</li>
<li><p><strong>the review and evaluation events around that answer</strong></p>
</li>
<li><p><strong>the verified knowledge layer</strong></p>
</li>
</ul>
<p>That separation is important.</p>
<p>An archived answer is not automatically a fact. An archived answer is not automatically a memory. An archived answer is not automatically something the system should learn from.</p>
<p>It is simply <strong>what the model said at a particular point in time</strong>, plus the information needed to inspect, judge, and back it up.</p>
<p>The ledger is:</p>
<ul>
<li><p><strong>agent-isolated</strong></p>
</li>
<li><p><strong>excluded from Git</strong></p>
</li>
<li><p><strong>included in local backup</strong></p>
</li>
<li><p><strong>hash-checked for integrity</strong></p>
</li>
</ul>
<p>This makes it much easier to review a promising answer later, revise it, or reuse it as the basis for a blog post or a candidate social post—without pretending it already belongs in the fact layer.</p>
<h2>This is a much better stopping point than I had before</h2>
<p>At this stage, I do <strong>not</strong> think LifeWiki Lab has proven learning transfer in a strong sense. The earlier learning experiments still did not demonstrate robust positive improvement. And the baseball benchmark is still too small to justify grand claims about model superiority.</p>
<p>But this <em>is</em> a meaningful checkpoint.</p>
<p>By version <strong>v3.3.9</strong>, the system can now:</p>
<ul>
<li><p>run a frozen baseball benchmark locally or through a cloud provider</p>
</li>
<li><p>replay a single failing case with explicit cost controls</p>
</li>
<li><p>capture safe diagnostics and usage data</p>
</li>
<li><p>distinguish provider-shape failures from baseball-reasoning failures</p>
</li>
<li><p>preserve the visible model answer in a local artifact ledger</p>
</li>
<li><p>keep evaluation, review, and storage boundaries much cleaner than before</p>
</li>
</ul>
<p>That is real progress.</p>
<p>It is not flashy progress. It is the kind of progress that makes future experiments worth trusting.</p>
<h2>What comes next</h2>
<p>With the benchmark and observability layer in better shape, the next phase can finally aim back toward the original vision: a <strong>Baseball Discovery Engine</strong>.</p>
<img src="https://cdn.hashnode.com/uploads/covers/6ad628f812bb8921f3a79ac9/d5a50eab-c1d6-4f25-a21f-497671590f8d.png" alt="Roadmap graphic from verified research tools through benchmark replay and the artifact ledger to the upcoming Baseball Discovery Engine" style="display:block;margin:0 auto" />

<p><em>Figure 5. The next step is not autonomous posting. It is a reliable discovery workflow first.</em></p>
<p>The plan is straightforward:</p>
<ol>
<li><p>use verified baseball tools and stored datasets</p>
</li>
<li><p>generate candidate statistics and patterns</p>
</li>
<li><p>rank which findings look interesting enough to investigate</p>
</li>
<li><p>review them manually before turning them into any public output</p>
</li>
</ol>
<p>In other words: <strong>still no autonomous posting loop</strong>.</p>
<p>That restraint is deliberate.</p>
<p>Before an AI baseball analyst posts anything interesting, it should first be able to show:</p>
<ul>
<li><p>where the numbers came from</p>
</li>
<li><p>what the system actually said</p>
</li>
<li><p>how the answer was judged</p>
</li>
<li><p>what went wrong when it failed</p>
</li>
<li><p>and what a human accepted or rejected afterward</p>
</li>
</ul>
<p>That is the system I am trying to build.</p>
<p>And this phase taught me something important:</p>
<p><strong>Correct answers are necessary. They just are not enough.</strong></p>
<hr />
<p><em>This is the second entry in LifeWiki Lab, an independent engineering journal about AI memory, evidence, benchmarking, and trustworthy agent behavior. The next entry will likely begin the Baseball Discovery Engine phase.</em></p>
]]></content:encoded></item><item><title><![CDATA[I Built an AI That Remembers Its Mistakes. Now I Need to Prove It Can Learn.]]></title><description><![CDATA[Building an AI baseball nerd with persistent memory, SQLite, and local LLMs. Our first experiment asks whether remembering mistakes improves answers.]]></description><link>https://lifewiki-lab.hashnode.dev/can-ai-learn-from-its-mistakes</link><guid isPermaLink="true">https://lifewiki-lab.hashnode.dev/can-ai-learn-from-its-mistakes</guid><category><![CDATA[Artificial Intelligence]]></category><category><![CDATA[ai agents]]></category><category><![CDATA[Python]]></category><category><![CDATA[llm]]></category><category><![CDATA[Machine Learning]]></category><dc:creator><![CDATA[PeterHuesson]]></dc:creator><pubDate>Mon, 19 Oct 2026 19:29:34 GMT</pubDate><enclosure url="https://cdn.hashnode.com/uploads/covers/6ad628f812bb8921f3a79ac9/1f334a9b-2d6f-49f7-b4bd-a2720ead3d1a.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p><em>From a baseball-obsessed local language model to a reusable Python architecture for long-term memory, external verification, and honest learning experiments.</em></p>
<blockquote>
<p><strong>The experiment:</strong> What happens if we give an AI agent a persistent autobiography, a way to record corrections, and independent checks on its own claims? Can we make it improve—not just remember?</p>
</blockquote>
<p>I started this project with a fairly ridiculous ambition: I wanted an AI baseball nerd.</p>
<p>Not a chatbot that could recite a few famous statistics. A character with an obsessive interest in baseball history, enough personality to write its own entertaining posts, and the freedom—eventually—to go looking for strange stories in box scores and old games. Something closer to a persistent researcher than a question-answering interface.</p>
<p>The first reality check came quickly.</p>
<p>I ran <strong>Qwen3:4b locally through Ollama</strong> on my MacBook Air. When I asked about baseball's upcoming labor negotiations, the model confidently muddled the timeline: it referred to a lockout in the wrong year, assumed the wrong current date, and got the collective bargaining agreement's timeline wrong.</p>
<p>It wasn't an especially exotic failure. Language models can sound certain while being wrong. What bothered me more was the structural problem: <strong>even if I corrected the answer today, why should the system behave differently tomorrow?</strong></p>
<p>That question turned a baseball side project into <strong>LifeWiki Lab</strong>.</p>
<h2>Memory is not a longer chat history</h2>
<p>The first instinct is to keep feeding previous conversations back into the prompt. That's useful, but it isn't a long-term memory system. Context windows are finite. Important observations get buried. And a past model answer does not turn into verified knowledge just because it was written down.</p>
<p>I wanted a system that could make several distinctions:</p>
<ul>
<li><p><strong>What happened?</strong> An episode or observed event.</p>
</li>
<li><p><strong>What does the agent remember?</strong> A memory, not automatically a fact.</p>
</li>
<li><p><strong>What does it claim is true?</strong> A claim with an explicit verification status.</p>
</li>
<li><p><strong>Where did the evidence come from?</strong> A source with provenance.</p>
</li>
<li><p><strong>What is still unresolved?</strong> An open question.</p>
</li>
<li><p><strong>What is the agent's stored state?</strong> An agent-state record, separate from the model's generated persona.</p>
</li>
</ul>
<p>So I built a small, modular Python monolith around <strong>SQLite</strong>. Its six Wiki record types have stable IDs, revision histories, and explicit status rules. Old revisions are preserved. Markdown is generated as a readable export; the database remains the source of truth.</p>
<p>I deliberately avoided a large agent framework, a vector database, and an elaborate microservice architecture. I needed something understandable enough to inspect when a learning experiment went wrong.</p>
<img src="https://cdn.hashnode.com/uploads/covers/6ad628f812bb8921f3a79ac9/9898680a-e24e-4149-93c7-0e7648ea66ca.png" alt="Implemented LifeWiki architecture at v0.2.7, with baseball-specific integration marked" style="display:block;margin:0 auto" />

<p><em>Figure 1. Implemented components at v0.2.7. This is not yet a fully generic multi-agent runtime: baseball context is still wired into the chat orchestration, and there is no autonomous research loop.</em></p>
<p>The language model is replaceable behind a small text-generation interface. I have fake and cloud adapters for testing or optional use, and a local Ollama adapter for <strong>Qwen3:4b</strong>. The local path doesn't silently switch to a cloud provider.</p>
<p>That's the first architectural principle of this project: <strong>the model generates language; the application owns memory, permissions, and verification.</strong></p>
<h2>Give the baseball nerd something real to read</h2>
<p>A memory system full of hallucinations is not much of an upgrade.</p>
<p>For the first real data integration, I deliberately picked a tiny slice of <strong>Retrosheet's 2020 game information</strong>: regular-season games from July 23 through July 31 involving Boston (BOS) or the New York Yankees (NYA).</p>
<p>The import keeps the raw source files and hashes, builds a separate baseball SQLite database, and uses deterministic Python calculations rather than asking the model to do the bookkeeping itself.</p>
<p>The resulting summary is small enough to inspect:</p>
<img src="https://cdn.hashnode.com/uploads/covers/6ad628f812bb8921f3a79ac9/550487b5-4fb6-4cb7-9573-019897942cf6.png" alt="Retrosheet counts for Boston and New York, showing 14 team appearances but 13 unique games" style="display:block;margin:0 auto" />

<p><em>Figure 2. In this limited Retrosheet subset, BOS played 8 games (3–5) and NYA played 6 (5–1). One head-to-head game appears in both team totals. That makes</em> <em><strong>14 team appearances but 13 distinct games</strong></em><em>, not a complete season record.</em></p>
<p>Then something wonderfully appropriate happened: in an early integration run, the model treated those <strong>14 team appearances as 14 separate games</strong>.</p>
<p>The initial fix was not autonomous learning. We refined the application's instructions, and the final integration test produced the correct answer of 13 distinct games. That was a successful prompt-and-software correction—not evidence that the agent had taught itself anything.</p>
<p>But it gave us an actual learning case to work with.</p>
<h2>What does an AI actually learn from a mistake?</h2>
<p>Suppose an agent says, "There were 14 different games."</p>
<p>A Python evaluator checks the source dataset and determines that there were 13. The model can then generate a proposed lesson: when summing games across teams, account for games where those teams played each other.</p>
<p>Those are <strong>three different things</strong>:</p>
<ol>
<li><p>An observed statement and its original record.</p>
</li>
<li><p>An independently computed correction for that particular case.</p>
</li>
<li><p>A model-generated generalization that <strong>might</strong> help in the future.</p>
</li>
</ol>
<p>Treating all three as equally trustworthy would create a confident but self-reinforcing error machine.</p>
<p>In Sprint 2.4, I added a generic learning workflow that records an observation, requests an external evaluator's result, asks the model for a reflection, and atomically stores <strong>an Episode, a Memory, and an OpenQuestion</strong>. The reflection remains labeled as an <strong>unverified hypothesis</strong>. It never becomes a confirmed claim merely because an LLM wrote it.</p>
<p>The same engine processed two different cases: the real historical baseball miscount and a clearly labeled synthetic warehouse arithmetic mistake. There is no baseball-specific logic inside the learning workflow.</p>
<img src="https://cdn.hashnode.com/uploads/covers/6ad628f812bb8921f3a79ac9/9ea151b3-5f24-488c-b235-63fe2b56eb4d.png" alt="LifeWiki learning cycle and distinction between evaluated event and unverified transfer" style="display:block;margin:0 auto" />

<p><em>Figure 3. Our learning path. The original observation and external check are recorded separately from the model's hypothesis. Later recall revalidates the audit group; applying the hypothesis successfully is a separate test.</em></p>
<p>An important implementation detail emerged during the architecture audit: the initial version checked the three linked audit records when writing them, but not consistently when <strong>reading</strong> them back.</p>
<p>That meant a later edit to one memory could make it disagree with its companion episode and open question, while retrieval still presented the edited correction as externally checked.</p>
<p>We fixed that in Sprint 2.7. The recall path now validates the group of three records and both local evidence files. If a relevant learning record is inconsistent or its evidence cannot be verified, the request fails visibly <strong>before</strong> the model is called.</p>
<p>That's not proof of a true fact—hashes prove integrity, not truth, and a Python checker is only as trustworthy as its logic—but it closes an important gap between <em>storing</em> a learning event and <em>using</em> it later.</p>
<h2>The awkward part: our first learning test did not show learning</h2>
<p>I wanted to run the obvious experiment: ask the same model the same question <strong>with</strong> and <strong>without</strong> the stored learning memory.</p>
<p>The result was humbling.</p>
<img src="https://cdn.hashnode.com/uploads/covers/6ad628f812bb8921f3a79ac9/dafe1cb3-4a98-476f-bc82-b7b5db04640c.png" alt="Local A/B result: correct numeric answers in both conditions, no demonstrated improvement" style="display:block;margin:0 auto" />

<p><em>Figure 4. One local Qwen3:4b A/B run. Both conditions produced the correct numeric answers: 13 distinct games in the baseball case and 12 screws in the synthetic arithmetic case.</em></p>
<p>There were two limitations.</p>
<p>First, the baseline was already correct. The baseball prompt and statistics supplied enough information, and the existing instructions already included the right distinction. That's a <strong>ceiling effect</strong>: there was no obvious error left for the memory to fix.</p>
<p>Second, our automatic score had a bug. In the warehouse case, the answer <strong>with</strong> memory quoted the historical wrong number, "7 screws," to explain why it was wrong. The scorer saw the number and incorrectly counted that answer as an error. We preserved that original report and documented the problem rather than rewriting history.</p>
<p>The manual inspection gave a more careful conclusion:</p>
<p><strong>The storage-and-recall mechanism worked. A measurable improvement from learning was not demonstrated.</strong></p>
<p>It also exposed another weakness: our simple word-overlap retrieval occasionally pulled an unrelated baseball memory into the warehouse example. The database remembered something; it didn't always select the <em>right</em> thing.</p>
<p>I find this more interesting than a conveniently perfect demo. If a system is going to claim it learns, it needs tests where the model is genuinely challenged, new questions that weren't embedded in the stored correction, and scoring that distinguishes <strong>quoting an old mistake</strong> from <strong>making that mistake again</strong>.</p>
<p>The next evaluation will need held-out examples, cleaner retrieval, and separate comparisons of <em>no memory</em>, <em>verified correction only</em>, and <em>verified correction plus model reflection</em>.</p>
<h2>An architecture audit before adding more intelligence</h2>
<p>By this point I had enough moving parts to worry that I was building an increasingly complicated baseball-only application.</p>
<p>So I stopped feature development and ran a read-only architecture audit of the actual code and tests.</p>
<p>It found two problems worth fixing immediately:</p>
<p><strong>A database identity bug.</strong> The baseball importer knew not to open the Wiki database, but the Wiki store did not reliably recognize a baseball database. Under the wrong path, it could migrate the other database's schema. Sprint 2.6 added explicit Wiki database identification and safer read-only commands.</p>
<p><strong>A recall integrity bug.</strong> The learning audit records were checked as a group at write time, but could be inconsistent at read time. Sprint 2.7 added group-and-evidence validation on recall.</p>
<p>The result is not a finished framework. It's a firmer foundation, with <strong>355 offline tests passing</strong> at the Sprint 2.7 checkpoint, plus passing Ruff lint and format checks as reported in the project run. The repository was committed locally at Git tag <code>v0.2.7</code>.</p>
<img src="https://cdn.hashnode.com/uploads/covers/6ad628f812bb8921f3a79ac9/c7694a0e-c38b-42c9-bc99-896aef812c1d.png" alt="Timeline of LifeWiki development milestones through v0.2.7" style="display:block;margin:0 auto" />

<p><em>Figure 5. Selected milestones. Test counts establish regression coverage, not accuracy, consciousness, or demonstrated learning transfer.</em></p>
<p>The audit also confirmed an architectural limitation we still need to address: the chat layer knows about baseball, and agent identity is not yet configured as a strong operational boundary. That's why the next planned refactor separates a <strong>generic agent core</strong> from interchangeable domain contexts and isolated agent configurations.</p>
<h2>The baseball nerd is the experiment, not the architecture</h2>
<p>The long-term plan is bigger than baseball, but baseball remains the focus.</p>
<p>I want one engine that could eventually run a quirky baseball historian, a crypto-market researcher, or a completely different specialist—each with its own identity, sources, memories, evaluator, permissions, and history.</p>
<p>And yes, the same ideas might someday be useful for a genuinely personal assistant: one that remembers preferences, tracks corrections, and adapts its choices based on outcomes. <strong>That's a possible future application, not a pivot for this project.</strong></p>
<p>For now, the baseball nerd still has plenty to do. It cannot autonomously research the web, run a controlled multi-step agent loop, or publish its own posts. Nor do I have evidence that it performs better because it has remembered a lesson.</p>
<p>What I do have is an architecture that lets me test those claims instead of merely making them.</p>
<h2>What comes next</h2>
<p>The immediate work is less glamorous than a self-writing AI influencer:</p>
<ul>
<li><p>Separate domain-specific baseball context from the neutral chat core.</p>
</li>
<li><p>Give each agent a distinct identity, database, and evidence directory.</p>
</li>
<li><p>Improve the quality and relevance of retrieved lessons.</p>
</li>
<li><p>Design tougher, held-out learning tests and honest evaluation criteria.</p>
</li>
<li><p>Protect the eventual long-term memory with a tested backup-and-restore path.</p>
</li>
<li><p>Only then consider a bounded autonomous research loop and a baseball blog written by the agent itself—with human review before publication.</p>
</li>
</ul>
<p>My favorite outcome would be to watch the baseball nerd make a real mistake, get reliable feedback, save a carefully qualified lesson, and then handle a <strong>different</strong> situation better days later.</p>
<p>If that happens, I won't need to call it conscious, sentient, or magical.</p>
<p>I'll have something much more useful: <strong>an observable improvement, with a record of where it came from.</strong></p>
<p>And if the experiment fails, that goes in the lab notebook too.</p>
<hr />
<h3>Project notes and sources</h3>
<ul>
<li><p><strong>Project checkpoint:</strong> LifeWiki <code>v0.2.7</code>, locally committed as <code>82e2b64</code> (19 October 2026); the code repository has not been presented here as a public GitHub URL.</p>
</li>
<li><p><strong>Local stack:</strong> Python 3.11+ compatible design, SQLite, Ollama with Qwen3:4b, pytest, Ruff. Sprint 2.7 validation reported 355 passing offline tests.</p>
</li>
<li><p><strong>Baseball data:</strong> <a href="https://www.retrosheet.org/downloads/csvdownloads.html">Retrosheet CSV downloads</a> and <a href="https://www.retrosheet.org/downloads/csvcontents.html">CSV contents reference</a>. The limited, independently computed 2020 snapshot is not a full-season record.</p>
</li>
<li><p><strong>Attribution:</strong> The information used here was obtained free of charge from and is copyrighted by Retrosheet. Interested parties may contact Retrosheet at "<a href="http://www.retrosheet.org">www.retrosheet.org</a>".</p>
</li>
<li><p><strong>Methodological caveat:</strong> This article describes one observed local A/B comparison, not a statistically powered demonstration of general learning. Evidence hashes protect against unnoticed file changes; they do not establish source authenticity or correctness.</p>
</li>
</ul>
<p><em>This is the first entry in LifeWiki Lab, an engineering journal about building AI agents with persistent memory and testable learning. The initial test subject happens to be obsessed with baseball.</em></p>
]]></content:encoded></item></channel></rss>