<?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: Kevin Alemán</title>
    <description>The latest articles on DEV Community by Kevin Alemán (@kaleman15).</description>
    <link>https://dev.to/kaleman15</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%2F255126%2F6bdaeb84-6c1e-4e76-9d45-54c59eaac908.jpeg</url>
      <title>DEV Community: Kevin Alemán</title>
      <link>https://dev.to/kaleman15</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/kaleman15"/>
    <language>en</language>
    <item>
      <title>AI Has a Problem With Functional Programming</title>
      <dc:creator>Kevin Alemán</dc:creator>
      <pubDate>Thu, 15 Oct 2026 20:09:09 +0000</pubDate>
      <link>https://dev.to/kaleman15/ai-has-a-problem-with-functional-programming-kpm</link>
      <guid>https://dev.to/kaleman15/ai-has-a-problem-with-functional-programming-kpm</guid>
      <description>&lt;p&gt;There is a pattern I keep seeing in AI-generated code. You ask it to implement something relatively simple and you get this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;processRequest&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;request&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;processRequest&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;request&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;getData&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;request&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;transformData&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;getData&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;request&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;repository&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;request&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;transformData&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;mapper&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;transform&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Every function looks perfectly reasonable in isolation. But most of those functions add almost nothing. We've turned two operations into a small guided tour of the codebase.&lt;/p&gt;

&lt;p&gt;Very modular. I'm already tired.&lt;/p&gt;

&lt;p&gt;And yes, saying &lt;strong&gt;AI has a functional programming problem&lt;/strong&gt; is technically unfair. Functional programming isn't the issue. The problem is that LLMs seem unusually comfortable creating &lt;strong&gt;shallow abstractions&lt;/strong&gt;: functions whose only purpose is calling another function.&lt;/p&gt;

&lt;p&gt;And abstraction isn't free. Every function introduces another name, another place to jump to, another interface you need to keep in your head. You wanted to understand where the data comes from and now you're opening your fourth file.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fhpoo786zn1lg6s6jiv7l.webp" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fhpoo786zn1lg6s6jiv7l.webp" alt="A developer faces a winding route through five empty doorframes, while a short path leads directly to the same workbench." width="799" height="420"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Same job. More doors to open.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;John Ousterhout describes a similar problem with &lt;em&gt;shallow modules&lt;/em&gt;: abstractions whose interface is large relative to how much complexity they actually hide. They don't really remove complexity. They move it.&lt;/p&gt;


&lt;div class="crayons-card c-embed text-styles text-styles--secondary"&gt;
    &lt;div class="c-embed__content"&gt;
      &lt;div class="c-embed__body flex items-center justify-between"&gt;
        &lt;a href="https://web.stanford.edu/~ouster/cgi-bin/cs190-spring16/lecture.php?topic=modularDesign" rel="noopener noreferrer" class="c-link fw-bold flex items-center"&gt;
          &lt;span class="mr-2"&gt;web.stanford.edu&lt;/span&gt;
          

        &lt;/a&gt;
      &lt;/div&gt;
    &lt;/div&gt;
&lt;/div&gt;



&lt;h2&gt;
  
  
  Why does AI do this?
&lt;/h2&gt;

&lt;p&gt;There isn't much evidence that LLMs inherently &lt;em&gt;prefer&lt;/em&gt; functional or modular code.&lt;/p&gt;

&lt;p&gt;In fact, an EMNLP 2024 study compared modular and non-modular versions of functionally equivalent code across several code models. Their conclusion was interesting: &lt;strong&gt;modularity itself was not a core factor in improving code-generation performance&lt;/strong&gt;.&lt;/p&gt;


&lt;div class="crayons-card c-embed text-styles text-styles--secondary"&gt;
    &lt;div class="c-embed__content"&gt;
        &lt;div class="c-embed__cover"&gt;
          &lt;a href="https://aclanthology.org/2024.findings-emnlp.676/" class="c-link align-middle" rel="noopener noreferrer"&gt;
            &lt;img alt="" src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Faclanthology.org%2Fthumb%2F2024.findings-emnlp.676.jpg" height="600" class="m-0" width="600"&gt;
          &lt;/a&gt;
        &lt;/div&gt;
      &lt;div class="c-embed__body"&gt;
        &lt;h2 class="fs-xl lh-tight"&gt;
          &lt;a href="https://aclanthology.org/2024.findings-emnlp.676/" rel="noopener noreferrer" class="c-link"&gt;
            Revisiting the Impact of Pursuing Modularity for Code Generation - ACL Anthology
          &lt;/a&gt;
        &lt;/h2&gt;
        &lt;div class="color-secondary fs-s flex items-center"&gt;
            &lt;img alt="favicon" class="c-embed__favicon m-0 mr-2 radius-0" src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Faclanthology.org%2Faclicon.ico" width="32" height="32"&gt;
          aclanthology.org
        &lt;/div&gt;
      &lt;/div&gt;
    &lt;/div&gt;
&lt;/div&gt;


&lt;p&gt;So the problem may be less about what the model &lt;em&gt;wants&lt;/em&gt; and more about what we ask it to produce. We constantly tell AI to write code that is:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;clean&lt;/li&gt;
&lt;li&gt;modular&lt;/li&gt;
&lt;li&gt;reusable&lt;/li&gt;
&lt;li&gt;maintainable&lt;/li&gt;
&lt;li&gt;single-responsibility&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Those are good goals. But they are incredibly easy to satisfy mechanically:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Take these five lines and give them a name.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;There you go. Clean code. We can all go home.&lt;/p&gt;

&lt;p&gt;The model also doesn't experience the code like we do. Creating another helper costs it almost nothing. A human maintaining the result six months later has to navigate through it, figure out whether the helper does anything special and discover that, no, it just calls the next one.&lt;/p&gt;

&lt;p&gt;And we're starting to get actual evidence that &lt;strong&gt;functionally correct LLM code can still have structural quality problems&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F9y6m6g6ghk1r4ifp0jvr.webp" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F9y6m6g6ghk1r4ifp0jvr.webp" alt="Two working control cabinets have green lights. One has tangled wiring and hard-to-reach components; the other keeps its wiring organized and components accessible." width="799" height="420"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Both lights are green. Guess which one you want to debug six months from now.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;An ICSE 2026 study measured how likely LLM-generated code was to contain code smells and found that generation strategy, model architecture, model size and, importantly, &lt;strong&gt;prompt formulation&lt;/strong&gt; influence those smells.&lt;/p&gt;


&lt;div class="crayons-card c-embed text-styles text-styles--secondary"&gt;
    &lt;div class="c-embed__content"&gt;
      &lt;div class="c-embed__body"&gt;
        &lt;h2 class="fs-xl lh-tight"&gt;
          &lt;a href="https://www.microsoft.com/en-us/research/publication/a-causal-perspective-on-measuring-explaining-and-mitigating-smells-in-llm-generated-code/" rel="noopener noreferrer" class="c-link"&gt;
            A Causal Perspective on Measuring, Explaining and Mitigating Smells in LLM-Generated Code - Microsoft Research
          &lt;/a&gt;
        &lt;/h2&gt;
        &lt;div class="color-secondary fs-s flex items-center"&gt;
          microsoft.com
        &lt;/div&gt;
      &lt;/div&gt;
    &lt;/div&gt;
&lt;/div&gt;


&lt;p&gt;Another 2026 study looking at real repositories found that code detected as likely AI-generated showed substantial &lt;strong&gt;intra-repository code cloning&lt;/strong&gt;. Basically, repeated code inside the same repository. That's another sign that generating locally reasonable code doesn't necessarily produce a cleaner system globally.&lt;/p&gt;


&lt;div class="crayons-card c-embed text-styles text-styles--secondary"&gt;
    &lt;div class="c-embed__content"&gt;
        &lt;div class="c-embed__cover"&gt;
          &lt;a href="https://arxiv.org/abs/2607.01867" class="c-link align-middle" rel="noopener noreferrer"&gt;
            &lt;img alt="" src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Farxiv.org%2Fstatic%2Fbrowse%2F0.3.4%2Fimages%2Farxiv-logo-fb.png" height="467" class="m-0" width="800"&gt;
          &lt;/a&gt;
        &lt;/div&gt;
      &lt;div class="c-embed__body"&gt;
        &lt;h2 class="fs-xl lh-tight"&gt;
          &lt;a href="https://arxiv.org/abs/2607.01867" rel="noopener noreferrer" class="c-link"&gt;
            [2607.01867] An Exploratory Study on LLM-Generated Code and Comments in Code Repositories
          &lt;/a&gt;
        &lt;/h2&gt;
          &lt;p class="truncate-at-3"&gt;
            The use of LLMs in software development has become increasingly widespread on tasks such as code generation and summarization. Reports from large technology companies showed that around 20% to 30% of their code are generated by LLMs. However, there remains skepticism about the practical usage of LLM-generated code and comments, such as concerns on more time for debugging the generated code and the unnaturalness of the generated comments. In this paper, we study the code and comments detected as likely to be generated by LLMs and their characteristics, the differences between company- and community-maintained repositories, and how likely bugs are associated with LLM-generated code. We conduct extensive experiments on active company- and community-maintained repositories from 2021 to 2025 using various tools and techniques that detect code and comments generated by LLMs. Based on our detector-based proxy analysis, the results suggest that code detected as likely to be generated by LLMs decreased over time and appeared frequently in test cases, while that of comments remains relatively stable. Proxy results further suggest that code detected as likely to be generated by LLMs shows substantial intra-repository code clones, whereas comments exhibit a relatively low proportion of grammatically correct sentences. In addition, the company-maintained repositories show a higher percentage of code and comments detected as likely to be generated by LLMs, and only a small percentage of the human-labelled bugs are detected as being likely associated with LLM-generated code.
          &lt;/p&gt;
        &lt;div class="color-secondary fs-s flex items-center"&gt;
            &lt;img alt="favicon" class="c-embed__favicon m-0 mr-2 radius-0" src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Farxiv.org%2Fstatic%2Fbrowse%2F0.3.4%2Fimages%2Ficons%2Ffavicon-32x32.png" width="32" height="32"&gt;
          arxiv.org
        &lt;/div&gt;
      &lt;/div&gt;
    &lt;/div&gt;
&lt;/div&gt;


&lt;p&gt;Maintainability research has moved far enough that researchers are now trying to predict the maintainability and code-smell characteristics of generated code &lt;strong&gt;before the model even generates it&lt;/strong&gt;. One October 2026 paper, PreMaQ, evaluated 2,695 tasks across four models and found that its predictions correlated meaningfully with the eventual maintainability metrics of the generated code.&lt;/p&gt;


&lt;div class="crayons-card c-embed text-styles text-styles--secondary"&gt;
    &lt;div class="c-embed__content"&gt;
        &lt;div class="c-embed__cover"&gt;
          &lt;a href="https://arxiv.org/abs/2610.05858" class="c-link align-middle" rel="noopener noreferrer"&gt;
            &lt;img alt="" src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Farxiv.org%2Fstatic%2Fbrowse%2F0.3.4%2Fimages%2Farxiv-logo-fb.png" height="467" class="m-0" width="800"&gt;
          &lt;/a&gt;
        &lt;/div&gt;
      &lt;div class="c-embed__body"&gt;
        &lt;h2 class="fs-xl lh-tight"&gt;
          &lt;a href="https://arxiv.org/abs/2610.05858" rel="noopener noreferrer" class="c-link"&gt;
            [2610.05858] PreMaQ: Predicting Maintainability-Related Quality of LLM-Generated Code Before Generation
          &lt;/a&gt;
        &lt;/h2&gt;
          &lt;p class="truncate-at-3"&gt;
            As large language models (LLMs) become increasingly capable of code generation, adopting generated code in software development requires assessing not only its functional correctness but also its maintainability-related quality. If such quality could be estimated before generation, developers could avoid the cost of generating, reviewing, and discarding low-quality code. Although prior work has shown that the functional correctness of the LLM-generated code can be predicted in advance, it remains unclear whether maintainability-related quality is similarly predictable. We introduce Pre-Generation Maintainability-Related Quality Prediction (PreMaQ), which predicts the Code Smell Score (CSS) and Maintainability Index (MI) of generated code from the internal representations of LLMs before generation. Our evaluation covers four open-weight LLMs and four Python code generation benchmarks, comprising 2,695 tasks in total. Our results show that predicted CSS and MI consistently correlate with their observed values across all 16 model-benchmark combinations, achieving mean Spearman rank correlations of 0.57 and 0.65, respectively. When used for model selection, PreMaQ achieves 59.5% of the maintainability-related quality improvement attainable by an ideal maintainability-based selector over random selection on tasks for which multiple models generate functionally correct code. Combining predictions from PreMaQ and prompt embeddings increases this proportion to 60.7%, indicating that the two signals are complementary. These findings suggest that PreMaQ can be used to predict and improve the maintainability-related quality of LLM-generated code.
          &lt;/p&gt;
        &lt;div class="color-secondary fs-s flex items-center"&gt;
            &lt;img alt="favicon" class="c-embed__favicon m-0 mr-2 radius-0" src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Farxiv.org%2Fstatic%2Fbrowse%2F0.3.4%2Fimages%2Ficons%2Ffavicon-32x32.png" width="32" height="32"&gt;
          arxiv.org
        &lt;/div&gt;
      &lt;/div&gt;
    &lt;/div&gt;
&lt;/div&gt;


&lt;p&gt;None of these studies proves that AI loves one-line wrappers. They do show that "the code works" doesn't tell you everything about the code you're going to maintain.&lt;/p&gt;

&lt;h2&gt;
  
  
  So how do we stop it?
&lt;/h2&gt;

&lt;p&gt;Tell the AI that &lt;strong&gt;abstractions need to pay rent&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fy70q5z6y027zgee94psl.webp" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fy70q5z6y027zgee94psl.webp" alt="Empty entrance facades pass a gear through unchanged, beside a workshop that hides useful machinery behind a small input hatch." width="800" height="421"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;A small entrance is useful when there's an actual workshop behind it.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;I've started preferring instructions closer to:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Do not extract a function merely to make another function shorter. Create an abstraction only when it hides meaningful complexity, represents a domain concept, or is genuinely reused. Avoid pass-through functions and one-line wrappers. Prefer fewer concepts and a shorter call path.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The ICSE study above found that prompt formulation materially affects the kinds of code smells models generate, and that targeted mitigation can reduce their occurrence. That doesn't mean this exact prompt has been scientifically blessed. It means being specific about what you want is probably more useful than asking for "clean code" and hoping we all agree on what that means.&lt;/p&gt;

&lt;p&gt;One final rule I like:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;If the function's name is basically an English translation of its body, consider deleting it.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Consider, not automatically delete. A one-liner that expresses a real domain rule can still be useful. But if the only reason it exists is that the other function was getting a little long, maybe we don't need it.&lt;/p&gt;

&lt;p&gt;AI is extremely good at producing more code. We're reaching the point where one of the most important skills when using it is asking it to produce less.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>programming</category>
      <category>softwareengineering</category>
      <category>cleancode</category>
    </item>
    <item>
      <title>I used AI to cheat my way to a 156-day reading streak</title>
      <dc:creator>Kevin Alemán</dc:creator>
      <pubDate>Tue, 13 Oct 2026 20:20:36 +0000</pubDate>
      <link>https://dev.to/kaleman15/i-used-ai-to-cheat-my-way-to-a-156-day-reading-streak-1mh4</link>
      <guid>https://dev.to/kaleman15/i-used-ai-to-cheat-my-way-to-a-156-day-reading-streak-1mh4</guid>
      <description>&lt;p&gt;I asked Codex to recover my Apple Books reading streak. Very important engineering work, obviously.&lt;/p&gt;

&lt;p&gt;Books showed two days. I had an 80-day run in the history, then a gap, then a few scattered reading days. It happens to the best of us. The app was reporting exactly what it had recorded. I wanted the old streak back anyway, so I asked an agent to fill the gap.&lt;/p&gt;

&lt;p&gt;It ended up showing &lt;strong&gt;156 days&lt;/strong&gt; and &lt;strong&gt;New Record&lt;/strong&gt;. I have read so much.&lt;/p&gt;

&lt;p&gt;Before we go any further: &lt;strong&gt;don't try this at home. This is cheating. Do actual reading.&lt;/strong&gt; The agent added reading time to dates that were below the goal. Those entries were manufactured. Nobody read 71 extra days while a script was running.&lt;/p&gt;

&lt;p&gt;But the process was interesting. It involved private Swift APIs, backups, a background process, and, of course, a cache. Apparently even my questionable reading decisions need cache invalidation.&lt;/p&gt;

&lt;h2&gt;
  
  
  Start with the embarrassing part
&lt;/h2&gt;

&lt;p&gt;My daily goal was one minute. One minute. Apple Books was already being very generous with me. Had it on 15 mins a day, but I had to travel and reduced to 1 minute (talk about commitment issues).&lt;/p&gt;

&lt;p&gt;The old streak ran from May 11 through July 29, 2026. Continuing it through October 13 would make 156 calendar days. Of those, 85 already met their goals: the original 80, plus five later dates. That left 71 dates to fill.&lt;/p&gt;

&lt;p&gt;Seventy had no daily record. August 1 had six seconds, so it needed another 54. How do you even get six seconds of reading? IDK. A date that already met its goal needed no changes, even if it contained much more reading time.&lt;/p&gt;

&lt;p&gt;The calculation was small enough:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# Pseudocode
&lt;/span&gt;&lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;day&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;requested_range&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;goal&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;stored_goal&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;day&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;default&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;60&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;recorded&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;recorded_seconds&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;day&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;default&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;additional&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;max&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;goal&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;recorded&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;additional&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="nf"&gt;increment_reading_time&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;day&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;additional&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;default_goal&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;60&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;The dates also needed the correct timezone. The edits used &lt;code&gt;America/El_Salvador&lt;/code&gt; and local noon, keeping each increment inside its intended calendar day. It would be a pretty annoying way to discover a timezone bug, after going through all this to change a number. A big part of this was possible (within the 5 hour window of my $20 codex subscription) thanks to the work previously done to understand the Apple books data model. Give it a read if you want to read about sqlite databases.&lt;/p&gt;


&lt;div class="ltag__link--embedded"&gt;
  &lt;div class="crayons-story "&gt;
  &lt;a href="https://dev.to/kaleman15/the-apple-books-data-model-1f8h" class="crayons-story__hidden-navigation-link"&gt;The Apple Books data model&lt;/a&gt;


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

          &lt;a href="/kaleman15" class="crayons-avatar  crayons-avatar--l  "&gt;
            &lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F255126%2F6bdaeb84-6c1e-4e76-9d45-54c59eaac908.jpeg" alt="kaleman15 profile" class="crayons-avatar__image" width="460" height="460"&gt;
          &lt;/a&gt;
        &lt;/div&gt;
        &lt;div&gt;
          &lt;div&gt;
            &lt;a href="/kaleman15" class="crayons-story__secondary fw-medium m:hidden"&gt;
              Kevin Alemán
            &lt;/a&gt;
            &lt;div class="profile-preview-card relative mb-4 s:mb-0 fw-medium hidden m:inline-block"&gt;
              
                Kevin Alemán
                
                
              
              &lt;div id="story-author-preview-content-3964567" class="profile-preview-card__content crayons-dropdown branded-7 p-4 pt-0"&gt;
                &lt;div class="gap-4 grid"&gt;
                  &lt;div class="-mt-4"&gt;
                    &lt;a href="/kaleman15" class="flex"&gt;
                      &lt;span class="crayons-avatar crayons-avatar--xl mr-2 shrink-0"&gt;
                        &lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F255126%2F6bdaeb84-6c1e-4e76-9d45-54c59eaac908.jpeg" class="crayons-avatar__image" alt="" width="460" height="460"&gt;
                      &lt;/span&gt;
                      &lt;span class="crayons-link crayons-subtitle-2 mt-5"&gt;Kevin Alemán&lt;/span&gt;
                    &lt;/a&gt;
                  &lt;/div&gt;
                  &lt;div class="print-hidden"&gt;
                    
                      Follow
                    
                  &lt;/div&gt;
                  &lt;div class="author-preview-metadata-container"&gt;&lt;/div&gt;
                &lt;/div&gt;
              &lt;/div&gt;
            &lt;/div&gt;

          &lt;/div&gt;
          &lt;a href="https://dev.to/kaleman15/the-apple-books-data-model-1f8h" class="crayons-story__tertiary fs-xs"&gt;&lt;time&gt;Jun 22&lt;/time&gt;&lt;span class="time-ago-indicator-initial-placeholder"&gt;&lt;/span&gt;&lt;/a&gt;
        &lt;/div&gt;
      &lt;/div&gt;

    &lt;/div&gt;

    &lt;div class="crayons-story__indention"&gt;
      &lt;h2 class="crayons-story__title crayons-story__title-full_post"&gt;
        &lt;a href="https://dev.to/kaleman15/the-apple-books-data-model-1f8h" id="article-link-3964567"&gt;
          The Apple Books data model
        &lt;/a&gt;
      &lt;/h2&gt;
        &lt;div class="crayons-story__tags"&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/macos"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;macos&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/sqlite"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;sqlite&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/programming"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;programming&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/database"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;database&lt;/a&gt;
        &lt;/div&gt;
      &lt;div class="crayons-story__bottom"&gt;
        &lt;div class="crayons-story__details"&gt;
          &lt;a href="https://dev.to/kaleman15/the-apple-books-data-model-1f8h" class="crayons-btn crayons-btn--s crayons-btn--ghost crayons-btn--icon-left"&gt;
            &lt;div class="multiple_reactions_aggregate"&gt;
              &lt;span class="multiple_reactions_icons_container"&gt;
                  &lt;span class="crayons_icon_container"&gt;
                    &lt;img src="https://assets.dev.to/assets/sparkle-heart-5f9bee3767e18deb1bb725290cb151c25234768a0e9a2bd39370c382d02920cf.svg" width="24" height="24"&gt;
                  &lt;/span&gt;
              &lt;/span&gt;
              &lt;span class="aggregate_reactions_counter"&gt;1&lt;span class="hidden s:inline"&gt;&amp;nbsp;reaction&lt;/span&gt;&lt;/span&gt;
            &lt;/div&gt;
          &lt;/a&gt;
            &lt;a href="https://dev.to/kaleman15/the-apple-books-data-model-1f8h#comments" class="crayons-btn crayons-btn--s crayons-btn--ghost crayons-btn--icon-left flex items-center"&gt;
              

              &lt;span class="hidden s:inline"&gt;Add&amp;nbsp;Comment&lt;/span&gt;
            &lt;/a&gt;
        &lt;/div&gt;
        &lt;div class="crayons-story__save"&gt;
          &lt;small class="crayons-story__tertiary fs-xs mr-2"&gt;
            6 min read
          &lt;/small&gt;
        &lt;/div&gt;
      &lt;/div&gt;
    &lt;/div&gt;
  &lt;/div&gt;
&lt;/div&gt;


&lt;/div&gt;
&lt;br&gt;


&lt;p&gt;Now, let's start.&lt;/p&gt;

&lt;h2&gt;
  
  
  Make the backup before getting clever
&lt;/h2&gt;

&lt;p&gt;The history file involved was:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;~/Library/Group Containers/group.com.apple.iBooks/CRDTModelLocalFile/ReadingHistoryModel
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Before changing it, Codex backed up the history, its context and sync metadata, and the relevant Books preferences. The SQLite context databases were copied through SQLite's backup API. A permanent backup went into Documents, separate from the scratch files.&lt;/p&gt;

&lt;p&gt;Then the experiments happened on copies. That was useful because some of the first attempts at calling Apple's private Swift code failed.&lt;/p&gt;

&lt;p&gt;An agent having access to your files is a good reason to make the original easy to restore. Keep the backup somewhere separate, give it a name you understand, and be clear about which dates the agent is allowed to change. In this case, the scope was the missing goal time within one specific streak.&lt;/p&gt;
&lt;h2&gt;
  
  
  The C bridge that called Apple's Swift code
&lt;/h2&gt;

&lt;p&gt;This was the part I wanted to understand properly. Codex found an operation in the installed frameworks:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;ReadingHistoryModel.incrementReadingTime(date:amount:defaultGoal:)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;But having a method name and calling the method are two separate problems. There was no available SDK module to import for this private interface. The tool used a C bridge to load the framework, resolve the Swift entry points, and call them with the required binary calling convention.&lt;/p&gt;

&lt;p&gt;The calls went in both directions. The Swift driver called ordinary C functions declared in &lt;code&gt;native.h&lt;/code&gt;. Those C functions called Apple's compiled Swift functions through typed function pointers. The framework was loaded at runtime with &lt;code&gt;dlopen&lt;/code&gt;; the C object file was linked into the driver at build time.&lt;/p&gt;

&lt;p&gt;Below is the complete C bridge used in this experiment, split into pieces so the explanation can stay next to the code. These are the actual functions and symbols used on this Mac. The Swift snippets are excerpts from the driver.&lt;/p&gt;
&lt;h3&gt;
  
  
  Start with the C interface
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;&lt;code&gt;native.h&lt;/code&gt;&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight c"&gt;&lt;code&gt;&lt;span class="cp"&gt;#include&lt;/span&gt; &lt;span class="cpf"&gt;&amp;lt;stdint.h&amp;gt;&lt;/span&gt;&lt;span class="cp"&gt;
&lt;/span&gt;&lt;span class="k"&gt;typedef&lt;/span&gt; &lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="kt"&gt;uint64_t&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="n"&gt;Bits&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="nf"&gt;history_decode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;uint64_t&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;uint64_t&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="n"&gt;Bits&lt;/span&gt; &lt;span class="nf"&gt;history_describe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="n"&gt;Bits&lt;/span&gt; &lt;span class="nf"&gt;history_encode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;history_increment&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;double&lt;/span&gt; &lt;span class="n"&gt;date&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;int64_t&lt;/span&gt; &lt;span class="n"&gt;amount&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;int64_t&lt;/span&gt; &lt;span class="n"&gt;goal&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="nf"&gt;history_error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;void&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="nf"&gt;history_type&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;void&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;history_set_streak&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;dictionary_metadata&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;date&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;int64_t&lt;/span&gt; &lt;span class="n"&gt;length&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;&lt;code&gt;Bits&lt;/code&gt; carries two 64-bit words across the C boundary. On this installation, that matched the representation used for the &lt;code&gt;Data&lt;/code&gt; arguments and the &lt;code&gt;Data&lt;/code&gt; and &lt;code&gt;String&lt;/code&gt; results involved in these calls. Those words can contain storage references or inline information; they are the Swift value's representation, rather than a byte-buffer API.&lt;/p&gt;

&lt;p&gt;The C interface exposes opaque pointers for the model and its metadata. The driver uses &lt;code&gt;history_error()&lt;/code&gt; to retrieve a captured Swift error and &lt;code&gt;history_type()&lt;/code&gt; when reflecting on the model later.&lt;/p&gt;
&lt;h3&gt;
  
  
  Tell Clang how to call Swift
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;&lt;code&gt;native.c&lt;/code&gt; — attributes, function types, and symbol lookup&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight c"&gt;&lt;code&gt;&lt;span class="cp"&gt;#include&lt;/span&gt; &lt;span class="cpf"&gt;"native.h"&lt;/span&gt;&lt;span class="cp"&gt;
#include&lt;/span&gt; &lt;span class="cpf"&gt;&amp;lt;dlfcn.h&amp;gt;&lt;/span&gt;&lt;span class="cp"&gt;
#include&lt;/span&gt; &lt;span class="cpf"&gt;&amp;lt;assert.h&amp;gt;&lt;/span&gt;&lt;span class="cp"&gt;
#include&lt;/span&gt; &lt;span class="cpf"&gt;&amp;lt;stdio.h&amp;gt;&lt;/span&gt;&lt;span class="cp"&gt;
#include&lt;/span&gt; &lt;span class="cpf"&gt;&amp;lt;stdlib.h&amp;gt;&lt;/span&gt;&lt;span class="cp"&gt;
#define SWIFT __attribute__((swiftcall))
#define SELF __attribute__((swift_context))
#define ERROR __attribute__((swift_error_result))
#define RESULT __attribute__((swift_indirect_result))
&lt;/span&gt;&lt;span class="k"&gt;typedef&lt;/span&gt; &lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="kt"&gt;uintptr_t&lt;/span&gt; &lt;span class="n"&gt;state&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="n"&gt;MetadataResponse&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;typedef&lt;/span&gt; &lt;span class="n"&gt;MetadataResponse&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;MetadataFn&lt;/span&gt;&lt;span class="p"&gt;)(&lt;/span&gt;&lt;span class="kt"&gt;uintptr_t&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;SWIFT&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;typedef&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;DecodeFn&lt;/span&gt;&lt;span class="p"&gt;)(&lt;/span&gt;&lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;RESULT&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;uint64_t&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;uint64_t&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;SELF&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="o"&gt;**&lt;/span&gt; &lt;span class="n"&gt;ERROR&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;SWIFT&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;typedef&lt;/span&gt; &lt;span class="n"&gt;Bits&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;BitsFn&lt;/span&gt;&lt;span class="p"&gt;)(&lt;/span&gt;&lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;SELF&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;SWIFT&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;typedef&lt;/span&gt; &lt;span class="n"&gt;Bits&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;EncodeFn&lt;/span&gt;&lt;span class="p"&gt;)(&lt;/span&gt;&lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;SELF&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="o"&gt;**&lt;/span&gt; &lt;span class="n"&gt;ERROR&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;SWIFT&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;typedef&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;IncrementFn&lt;/span&gt;&lt;span class="p"&gt;)(&lt;/span&gt;&lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;int64_t&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;int64_t&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;SELF&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;SWIFT&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;metadata&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;witness&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;last_error&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="nf"&gt;history_error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;void&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;last_error&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="nf"&gt;history_type&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;void&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;metadata&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="nf"&gt;symbol&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;const&lt;/span&gt; &lt;span class="kt"&gt;char&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;value&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;dlsym&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;RTLD_DEFAULT&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;fprintf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;stderr&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"Missing symbol: %s&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="n"&gt;exit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;The attributes carry the calling-convention information:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Macro&lt;/th&gt;
&lt;th&gt;Role in the bridge&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;SWIFT&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Call the function using Swift's calling convention&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;SELF&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Give the context parameter its special Swift ABI treatment&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;RESULT&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Pass storage for an indirectly returned value&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;ERROR&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Receive the error result from a throwing Swift call&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;blockquote&gt;
&lt;h1&gt;
  
  
  What's ABI
&lt;/h1&gt;

&lt;p&gt;No, it's not the name of a girl ;) even tho it may be. ABI stands for Application Binary Interface. In short, it defines how already compiled Swift code interacts at the binary level and how the code talks to the runtime.&lt;br&gt;
Type layout conventions, representation, metadata, etc.&lt;br&gt;
You can find way more about this on the web, and probably better explained :)&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Clang still needs a function type that describes the lowered arguments correctly. &lt;code&gt;swiftcall&lt;/code&gt; handles their low-level placement; the bridge must supply indirect pointers, generic arguments, context, and error parameters in the right shape. The &lt;a href="https://clang.llvm.org/docs/AttributeReference.html#swiftcall" rel="noopener noreferrer"&gt;Clang attribute reference&lt;/a&gt; documents this distinction.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;symbol()&lt;/code&gt; helper resolves an address with &lt;code&gt;dlsym&lt;/code&gt;. The &lt;code&gt;$s...&lt;/code&gt; strings are Swift's mangled symbol names. They carry information about the module, type, operation, and signature. One of the names used here can be inspected with:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;xcrun swift-demangle &lt;span class="nt"&gt;--compact&lt;/span&gt; &lt;span class="s1"&gt;'$s13BookDataStore19ReadingHistoryModelV09incrementD4Time4date6amount11defaultGoaly10Foundation4DateV_S2itF'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;The result identifies &lt;code&gt;ReadingHistoryModel.incrementReadingTime(date:amount:defaultGoal:)&lt;/code&gt;. Finding that address gives us a place to call. The typedef determines how the call gets there.&lt;/p&gt;
&lt;h3&gt;
  
  
  Decode a type C doesn't know about
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;&lt;code&gt;native.c&lt;/code&gt; — loading and decoding&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight c"&gt;&lt;code&gt;&lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="nf"&gt;history_decode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;uint64_t&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;uint64_t&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;assert&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;dlopen&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"/System/Library/PrivateFrameworks/BookDataStore.framework/BookDataStore"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;RTLD_NOW&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;RTLD_GLOBAL&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
    &lt;span class="n"&gt;MetadataFn&lt;/span&gt; &lt;span class="n"&gt;meta&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;symbol&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"$s13BookDataStore19ReadingHistoryModelVMa"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="n"&gt;metadata&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;meta&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;conforms&lt;/span&gt;&lt;span class="p"&gt;)(&lt;/span&gt;&lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;symbol&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"swift_conformsToProtocol"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="n"&gt;witness&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;conforms&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;metadata&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;symbol&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"$s9Coherence4CRDTMp"&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
    &lt;span class="n"&gt;assert&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;metadata&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="n"&gt;witness&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="kt"&gt;uintptr_t&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;vwt&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="kt"&gt;uintptr_t&lt;/span&gt; &lt;span class="o"&gt;**&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="n"&gt;metadata&lt;/span&gt;&lt;span class="p"&gt;)[&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
    &lt;span class="kt"&gt;size_t&lt;/span&gt; &lt;span class="n"&gt;size&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;vwt&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;8&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
    &lt;span class="n"&gt;assert&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;size&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="n"&gt;size&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="mi"&gt;4096&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;model&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;calloc&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;size&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;error&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;NULL&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="n"&gt;DecodeFn&lt;/span&gt; &lt;span class="n"&gt;decode&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;symbol&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"$s9Coherence4CRDTPAAE14serializedDatax10Foundation0D0V_tKcfC"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="n"&gt;decode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;metadata&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;witness&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;metadata&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;error&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;error&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;last_error&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;error&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nb"&gt;NULL&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="n"&gt;fprintf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;stderr&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"Native model decoded (%zu bytes)&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;size&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;&lt;code&gt;dlopen&lt;/code&gt; loads &lt;code&gt;BookDataStore&lt;/code&gt;. &lt;code&gt;RTLD_GLOBAL&lt;/code&gt; makes its loaded exports available to the subsequent &lt;code&gt;RTLD_DEFAULT&lt;/code&gt; lookups; the required Coherence symbols were available through the loaded dependencies.&lt;/p&gt;

&lt;p&gt;The metadata accessor returns the runtime type information for &lt;code&gt;ReadingHistoryModel&lt;/code&gt;. &lt;code&gt;MetadataResponse&lt;/code&gt; models its pointer-and-state result; &lt;code&gt;meta(0).value&lt;/code&gt; keeps the metadata pointer. &lt;code&gt;swift_conformsToProtocol&lt;/code&gt; then retrieves its conformance to &lt;code&gt;Coherence.CRDT&lt;/code&gt;. That conformance is represented by a witness table: the information the generic decoder needs to use this particular type's implementation.&lt;/p&gt;

&lt;p&gt;C also needs somewhere to put the decoded value. The pointer immediately before the metadata points to its value witness table, which includes layout and value-management information. The bridge reads the size slot used by this ABI, allocates storage, and passes it as the indirect result. The decoded model occupied 24 bytes in this run. Swift's &lt;a href="https://github.com/swiftlang/swift/blob/main/docs/ABI/TypeMetadata.rst" rel="noopener noreferrer"&gt;type metadata documentation&lt;/a&gt; describes the metadata and value witness table relationship.&lt;/p&gt;

&lt;p&gt;The decoder call has more arguments than its Swift source-level spelling suggests. It receives the output storage, the two &lt;code&gt;Data&lt;/code&gt; words, generic type metadata, the protocol witness table, the initializer's metatype context, and the error result. The metadata pointer appears twice because those are distinct roles in this entry point.&lt;/p&gt;

&lt;p&gt;The driver supplied the &lt;code&gt;Data&lt;/code&gt; representation like this:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight swift"&gt;&lt;code&gt;&lt;span class="kd"&gt;import&lt;/span&gt; &lt;span class="kt"&gt;Foundation&lt;/span&gt;

&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="nv"&gt;arguments&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kt"&gt;CommandLine&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;arguments&lt;/span&gt;
&lt;span class="k"&gt;guard&lt;/span&gt; &lt;span class="n"&gt;arguments&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;count&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;=&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nf"&gt;fatalError&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"input output [increments.json]"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="nv"&gt;data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="kt"&gt;Data&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;contentsOf&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;URL&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;fileURLWithPath&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;arguments&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;]))&lt;/span&gt;
&lt;span class="nf"&gt;precondition&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;MemoryLayout&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kt"&gt;Data&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;.&lt;/span&gt;&lt;span class="n"&gt;size&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="kt"&gt;MemoryLayout&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kt"&gt;Bits&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;.&lt;/span&gt;&lt;span class="n"&gt;size&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="nv"&gt;bits&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;unsafeBitCast&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;to&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;Bits&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="k"&gt;self&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;guard&lt;/span&gt; &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="nv"&gt;model&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;history_decode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;bits&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;bits&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="nv"&gt;error&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;unsafeBitCast&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;history_error&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;to&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;any&lt;/span&gt; &lt;span class="kt"&gt;Error&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="k"&gt;self&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Native decode failed: &lt;/span&gt;&lt;span class="se"&gt;\(&lt;/span&gt;&lt;span class="n"&gt;error&lt;/span&gt;&lt;span class="se"&gt;)&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="nf"&gt;exit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;&lt;code&gt;unsafeBitCast&lt;/code&gt; reinterprets the value's bits. The size check catches a size mismatch, but it does not establish that an arbitrary Swift type can safely be passed this way. This bridge depended on the representation and ownership behavior of these specific calls.&lt;/p&gt;
&lt;h3&gt;
  
  
  Inspect and serialize the model
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;&lt;code&gt;native.c&lt;/code&gt; — description and encoding&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight c"&gt;&lt;code&gt;&lt;span class="n"&gt;Bits&lt;/span&gt; &lt;span class="nf"&gt;history_describe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;BitsFn&lt;/span&gt; &lt;span class="n"&gt;describe&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;symbol&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"$s13BookDataStore19ReadingHistoryModelV16debugDescriptionSSvg"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;describe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="n"&gt;Bits&lt;/span&gt; &lt;span class="nf"&gt;history_encode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;EncodeFn&lt;/span&gt; &lt;span class="n"&gt;encode&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;symbol&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"$s9Coherence11CRMergeableP14serializedData_7version10Foundation0D0VAA9CRContextC_AA16CRCodableVersionOtKFTj"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;conforms&lt;/span&gt;&lt;span class="p"&gt;)(&lt;/span&gt;&lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;symbol&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"swift_conformsToProtocol"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;mergeable_witness&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;conforms&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;metadata&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;symbol&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"$s9Coherence11CRMergeableMp"&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
    &lt;span class="n"&gt;assert&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;mergeable_witness&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="n"&gt;MetadataFn&lt;/span&gt; &lt;span class="n"&gt;context_meta&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;symbol&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"$s9Coherence9CRContextCMa"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;create_context&lt;/span&gt;&lt;span class="p"&gt;)(&lt;/span&gt;&lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;SELF&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;SWIFT&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;symbol&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"$s9Coherence9CRContextC6sharedACvgZ"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;context&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;create_context&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;context_meta&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="kt"&gt;uint8_t&lt;/span&gt; &lt;span class="n"&gt;version&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;uint32_t&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="n"&gt;symbol&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"$s9Coherence16CRCodableVersionO8version3yA2CmFWC"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;error&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;NULL&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="n"&gt;Bits&lt;/span&gt; &lt;span class="n"&gt;bits&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;encode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;version&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;metadata&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;mergeable_witness&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;error&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;error&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;last_error&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;error&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Bits&lt;/span&gt;&lt;span class="p"&gt;){&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;};&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;bits&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;&lt;code&gt;history_describe&lt;/code&gt; calls the model's debug-description getter. The Swift driver interprets the returned &lt;code&gt;Bits&lt;/code&gt; as a &lt;code&gt;String&lt;/code&gt; and uses that description in its round-trip checks.&lt;/p&gt;

&lt;p&gt;Encoding uses a separate &lt;code&gt;CRMergeable&lt;/code&gt; conformance, its serialization dispatch thunk, and the shared &lt;code&gt;CRContext&lt;/code&gt;. The bridge resolves the installed enum case tag for &lt;code&gt;version3&lt;/code&gt; and passes its address to the encoder. That tag lookup and argument representation were checked for this installation.&lt;/p&gt;

&lt;p&gt;Both throwing calls start with a null error pointer. On failure, the bridge captures the returned error for the driver. On success, encoding returns the representation of a Swift &lt;code&gt;Data&lt;/code&gt; value, which the driver writes to a scratch file and decodes again before any live replacement.&lt;/p&gt;
&lt;h3&gt;
  
  
  The increment, and the pointer that mattered
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;&lt;code&gt;native.c&lt;/code&gt; — adding reading time&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight c"&gt;&lt;code&gt;&lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;history_increment&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;double&lt;/span&gt; &lt;span class="n"&gt;date&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;int64_t&lt;/span&gt; &lt;span class="n"&gt;amount&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;int64_t&lt;/span&gt; &lt;span class="n"&gt;goal&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;IncrementFn&lt;/span&gt; &lt;span class="n"&gt;increment&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;symbol&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"$s13BookDataStore19ReadingHistoryModelV09incrementD4Time4date6amount11defaultGoaly10Foundation4DateV_S2itF"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="n"&gt;increment&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;date&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;amount&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;goal&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;This is the function that added the missing seconds. The driver already had the intended day and the amount needed to reach its goal:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight swift"&gt;&lt;code&gt;&lt;span class="nf"&gt;history_increment&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;date&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;timeIntervalSinceReferenceDate&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="kt"&gt;Int64&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;edit&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;"amount"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="mi"&gt;60&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;The important detail in C is &lt;code&gt;increment(&amp;amp;date, amount, goal, model)&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;For this entry point on the installed build, Swift expected &lt;code&gt;Date&lt;/code&gt; indirectly. Its storage contained the reference-date time interval, so the wrapper put that value in a local &lt;code&gt;double&lt;/code&gt; and passed its address. The &lt;code&gt;model&lt;/code&gt; pointer received the Swift context treatment specified by &lt;code&gt;SELF&lt;/code&gt;. The &lt;code&gt;int64_t&lt;/code&gt; arguments also assumed the 64-bit &lt;code&gt;Swift.Int&lt;/code&gt; representation used on this Mac.&lt;/p&gt;

&lt;p&gt;An earlier attempt declared the date as a directly passed &lt;code&gt;double&lt;/code&gt;. The scratch process crashed inside &lt;code&gt;Calendar.component(_:from:)&lt;/code&gt;, attempting to read address &lt;code&gt;0x3c&lt;/code&gt;: decimal 60, one of the other argument values. The callee was reading the wrong thing as its date pointer. A small Swift probe compiled to LLVM IR confirmed the indirect date argument.&lt;/p&gt;

&lt;p&gt;That's a fairly concrete reason to inspect the calling convention before trusting a function-pointer cast. The compiler can accept the cast while the call is still wrong.&lt;/p&gt;
&lt;h3&gt;
  
  
  Update the record dictionary
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;&lt;code&gt;native.c&lt;/code&gt; — adding streak milestones&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight c"&gt;&lt;code&gt;&lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;history_set_streak&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;dictionary_metadata&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;date&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;int64_t&lt;/span&gt; &lt;span class="n"&gt;length&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kt"&gt;intptr_t&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;offset&lt;/span&gt;&lt;span class="p"&gt;)(&lt;/span&gt;&lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;intptr_t&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;symbol&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"swift_reflectionMirror_recursiveChildOffset"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="kt"&gt;intptr_t&lt;/span&gt; &lt;span class="n"&gt;field_offset&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;offset&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;metadata&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="n"&gt;assert&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;field_offset&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="mi"&gt;8&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;set&lt;/span&gt;&lt;span class="p"&gt;)(&lt;/span&gt;&lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;SELF&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;SWIFT&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;symbol&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"$s9Coherence15CRDictionary_v1Vyq_Sgxcis"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="n"&gt;set&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;date&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;length&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;dictionary_metadata&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;char&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="n"&gt;model&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;field_offset&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;The Swift driver reflected on the decoded model, checked that the selected field was named &lt;code&gt;streakRecords&lt;/code&gt;, and obtained its dictionary type metadata. On this build, it was &lt;code&gt;CRDictionary_v1&amp;lt;Int, Date&amp;gt;&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;The C helper asks for the field's offset, asserts the observed eight-byte offset, and calls the installed dictionary setter. The setter gets the optional date value, the integer key, the dictionary metadata, and the address of the dictionary field as its Swift context.&lt;/p&gt;

&lt;p&gt;The date argument here is a pointer to the actual Swift &lt;code&gt;Date?&lt;/code&gt; representation. The driver prepared it with:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight swift"&gt;&lt;code&gt;&lt;span class="k"&gt;var&lt;/span&gt; &lt;span class="nv"&gt;date&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;Date&lt;/span&gt;&lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;start&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;addingTimeInterval&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;Double&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;length&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="mi"&gt;86400&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="nf"&gt;withUnsafeMutablePointer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;to&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;date&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nf"&gt;history_set_streak&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;dictionaryMetadata&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;Int64&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;length&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;That allowed the native setter to add milestones 81 through 156 while keeping the existing records. The field index, offset, dictionary type, and symbol name are all assumptions that need checking on another build.&lt;/p&gt;
&lt;h3&gt;
  
  
  Build the bridge and the driver
&lt;/h3&gt;

&lt;p&gt;In the scratch directory, the build commands were:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;clang &lt;span class="nt"&gt;-c&lt;/span&gt; native.c &lt;span class="nt"&gt;-o&lt;/span&gt; native.o

swiftc &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-module-cache-path&lt;/span&gt; /private/tmp/books-streak-recovery/module-cache &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-import-objc-header&lt;/span&gt; native.h &lt;span class="se"&gt;\&lt;/span&gt;
  repair.swift native.o &lt;span class="nt"&gt;-o&lt;/span&gt; repair
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;&lt;code&gt;-import-objc-header&lt;/code&gt; exposes the C declarations to the Swift driver; the header itself contains ordinary C. Linking &lt;code&gt;native.o&lt;/code&gt; supplies those helper implementations. The private Swift entry points are resolved later, when the running tool loads the framework.&lt;/p&gt;

&lt;p&gt;The full driver also handled the requested dates, error reporting, serialization, and verification. The snippets above focus on the language boundary.&lt;/p&gt;
&lt;h3&gt;
  
  
  Keep the assumptions visible
&lt;/h3&gt;

&lt;p&gt;This was a short-lived repair process with global state and build-specific layout assumptions. It leaves decoded allocations alive until process exit. A reusable library would need proper Swift value destruction, ownership and alignment handling, allocation checks, and a fuller error lifecycle. &lt;em&gt;But the goal is to not make this an habit and start reading like a functional human being&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;There is also a very practical footgun in the actual code: &lt;code&gt;dlopen&lt;/code&gt; sits inside &lt;code&gt;assert&lt;/code&gt;. These builds had assertions enabled. Defining &lt;code&gt;NDEBUG&lt;/code&gt; would remove the framework load along with the check; a maintained implementation should load it separately and handle failure explicitly.&lt;/p&gt;

&lt;p&gt;The code is here because it explains what made the experiment work. It should also explain why I keep saying to leave your reading-history files alone.&lt;/p&gt;
&lt;h2&gt;
  
  
  And then Books still said two days
&lt;/h2&gt;

&lt;p&gt;After the daily entries were filled, Books recognized another completed day in the current week. The streak still said two days. The record still said 80.&lt;/p&gt;

&lt;p&gt;Of course there was more state. It's Apple, there should be something else, somewhere.&lt;/p&gt;

&lt;p&gt;Three pieces needed to agree:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The daily history needed enough credited time for the missing dates.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;streakRecords&lt;/code&gt; needed the newly reached streak lengths and their dates.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;ReadingHistory.CurrentStreak&lt;/code&gt; needed the new cached count.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The record dictionary ended at 80 days. Codex preserved those entries and added milestones 81 through 156, dated July 30 through October 13. We had to populate this data too.&lt;/p&gt;

&lt;p&gt;Swift reflection identified the record field and its dictionary type, and the bridge used the installed dictionary implementation's setter. Another check confirmed that these changes left the daily history unchanged. Finally, with Books closed, the cached count was updated:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;BOOKS_PREFS&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;/Library/Containers/com.apple.iBooksX/Data/Library/Preferences/com.apple.iBooksX.plist"&lt;/span&gt;

defaults write &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$BOOKS_PREFS&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; ReadingHistory.CurrentStreak &lt;span class="nt"&gt;-int&lt;/span&gt; 156
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;That command only handles the cache. The daily records and streak milestones had already been edited. &lt;code&gt;ReadingHistory.LastStreakDate&lt;/code&gt; already contained &lt;code&gt;20261013&lt;/code&gt;, so it stayed unchanged.&lt;/p&gt;
&lt;h2&gt;
  
  
  Make the app use the edited history
&lt;/h2&gt;

&lt;p&gt;Books and &lt;code&gt;bookdatastored&lt;/code&gt; can keep history in memory. Editing the file while they're using it creates an opportunity for a later write to replace your changes. Then we had to close Books app for the cache to be read again.&lt;/p&gt;

&lt;p&gt;Before replacement, the live daily history was compared with the version used to prepare the edits. The validated file was staged beside the live one, given the same permissions, flushed, and installed with &lt;code&gt;os.replace&lt;/code&gt;. The cache was refreshed while Books remained closed.&lt;/p&gt;

&lt;p&gt;Opening Books started the helper again. This time, Reading Goals showed &lt;strong&gt;156 days&lt;/strong&gt;, a &lt;strong&gt;156-day record&lt;/strong&gt;, and &lt;strong&gt;New Record&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;The checks covered both the file and the app. The serialized output was decoded again, its model description was compared with the in-memory result, and every daily date, time, and goal was checked. The app then confirmed that it was displaying the intended result. FINALLY!&lt;/p&gt;
&lt;h2&gt;
  
  
  The advice I should probably follow
&lt;/h2&gt;

&lt;p&gt;There's an awkward connection to my last article about AI. I wrote about how much easier it is becoming to produce a result, and how we still need to pay attention to the work and understanding behind it:&lt;/p&gt;


&lt;div class="ltag__link--embedded"&gt;
  &lt;div class="crayons-story "&gt;
  &lt;a href="https://dev.to/kaleman15/the-future-after-ai-2767" class="crayons-story__hidden-navigation-link"&gt;The future, after AI&lt;/a&gt;


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

          &lt;a href="/kaleman15" class="crayons-avatar  crayons-avatar--l  "&gt;
            &lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F255126%2F6bdaeb84-6c1e-4e76-9d45-54c59eaac908.jpeg" alt="kaleman15 profile" class="crayons-avatar__image" width="460" height="460"&gt;
          &lt;/a&gt;
        &lt;/div&gt;
        &lt;div&gt;
          &lt;div&gt;
            &lt;a href="/kaleman15" class="crayons-story__secondary fw-medium m:hidden"&gt;
              Kevin Alemán
            &lt;/a&gt;
            &lt;div class="profile-preview-card relative mb-4 s:mb-0 fw-medium hidden m:inline-block"&gt;
              
                Kevin Alemán
                
                
              
              &lt;div id="story-author-preview-content-4819808" class="profile-preview-card__content crayons-dropdown branded-7 p-4 pt-0"&gt;
                &lt;div class="gap-4 grid"&gt;
                  &lt;div class="-mt-4"&gt;
                    &lt;a href="/kaleman15" class="flex"&gt;
                      &lt;span class="crayons-avatar crayons-avatar--xl mr-2 shrink-0"&gt;
                        &lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F255126%2F6bdaeb84-6c1e-4e76-9d45-54c59eaac908.jpeg" class="crayons-avatar__image" alt="" width="460" height="460"&gt;
                      &lt;/span&gt;
                      &lt;span class="crayons-link crayons-subtitle-2 mt-5"&gt;Kevin Alemán&lt;/span&gt;
                    &lt;/a&gt;
                  &lt;/div&gt;
                  &lt;div class="print-hidden"&gt;
                    
                      Follow
                    
                  &lt;/div&gt;
                  &lt;div class="author-preview-metadata-container"&gt;&lt;/div&gt;
                &lt;/div&gt;
              &lt;/div&gt;
            &lt;/div&gt;

          &lt;/div&gt;
          &lt;a href="https://dev.to/kaleman15/the-future-after-ai-2767" class="crayons-story__tertiary fs-xs"&gt;&lt;time&gt;Oct 8&lt;/time&gt;&lt;span class="time-ago-indicator-initial-placeholder"&gt;&lt;/span&gt;&lt;/a&gt;
        &lt;/div&gt;
      &lt;/div&gt;

    &lt;/div&gt;

    &lt;div class="crayons-story__indention"&gt;
      &lt;h2 class="crayons-story__title crayons-story__title-full_post"&gt;
        &lt;a href="https://dev.to/kaleman15/the-future-after-ai-2767" id="article-link-4819808"&gt;
          The future, after AI
        &lt;/a&gt;
      &lt;/h2&gt;
        &lt;div class="crayons-story__tags"&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/ai"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;ai&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/programming"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;programming&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/career"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;career&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/beginners"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;beginners&lt;/a&gt;
        &lt;/div&gt;
      &lt;div class="crayons-story__bottom"&gt;
        &lt;div class="crayons-story__details"&gt;
          &lt;a href="https://dev.to/kaleman15/the-future-after-ai-2767" class="crayons-btn crayons-btn--s crayons-btn--ghost crayons-btn--icon-left"&gt;
            &lt;div class="multiple_reactions_aggregate"&gt;
              &lt;span class="multiple_reactions_icons_container"&gt;
                  &lt;span class="crayons_icon_container"&gt;
                    &lt;img src="https://assets.dev.to/assets/sparkle-heart-5f9bee3767e18deb1bb725290cb151c25234768a0e9a2bd39370c382d02920cf.svg" width="24" height="24"&gt;
                  &lt;/span&gt;
              &lt;/span&gt;
              &lt;span class="aggregate_reactions_counter"&gt;2&lt;span class="hidden s:inline"&gt;&amp;nbsp;reactions&lt;/span&gt;&lt;/span&gt;
            &lt;/div&gt;
          &lt;/a&gt;
            &lt;a href="https://dev.to/kaleman15/the-future-after-ai-2767#comments" class="crayons-btn crayons-btn--s crayons-btn--ghost crayons-btn--icon-left flex items-center"&gt;
              

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


&lt;/div&gt;
&lt;br&gt;


&lt;p&gt;Here I was, asking an agent to produce a very impressive number in a book app. It did the software work. It inspected the state, made the edits, and checked the result. My reading habit still needs me to open a book tomorrow, but I'll start from 156 rather than 2 ;)&lt;/p&gt;

&lt;p&gt;If you want something practical to do with Books, &lt;a href="https://support.apple.com/en-euro/guide/books/ibks7c41beea/9.0/mac/27" rel="noopener noreferrer"&gt;set a daily goal you can actually meet&lt;/a&gt;. On the Mac, that's under Home → Reading Goals → Adjust Goal. Then read. After a missed day, start another streak.&lt;/p&gt;

&lt;p&gt;Gotta be honest: my reading goal was &lt;code&gt;1 minute&lt;/code&gt; and even with that low value, I couldn't do it (commitment issues? who?).&lt;/p&gt;

&lt;p&gt;The fun lesson, as always, is: you can have the streak you want. It's just a number. The actual value is never in the milestone, is what you learn in the road :)&lt;/p&gt;

</description>
      <category>ai</category>
      <category>swift</category>
      <category>macos</category>
      <category>programming</category>
    </item>
    <item>
      <title>The future, after AI</title>
      <dc:creator>Kevin Alemán</dc:creator>
      <pubDate>Thu, 08 Oct 2026 19:52:28 +0000</pubDate>
      <link>https://dev.to/kaleman15/the-future-after-ai-2767</link>
      <guid>https://dev.to/kaleman15/the-future-after-ai-2767</guid>
      <description>&lt;p&gt;I've been using AI coding tools for a while now, and the progress is honestly insane. Something that would take a junior developer a day can sometimes be done by an agent in 20 minutes, with tests, documentation and probably better error handling than what I would've written on a Friday afternoon. That, alone, is insane: imagine the time you save on writing code and how you can invest that in some other stuff.  &lt;/p&gt;

&lt;p&gt;But there's something about this that has been bothering me lately:&lt;br&gt;&lt;br&gt;
&lt;strong&gt;What happens when producing good code no longer requires understanding how to produce good code?&lt;/strong&gt; &lt;br&gt;
And more importantly: &lt;strong&gt;what happens to the next generation of senior developers?&lt;/strong&gt;  &lt;/p&gt;

&lt;h2&gt;
  
  
  Juniors are becoming very productive
&lt;/h2&gt;

&lt;p&gt;Imagine you're learning backend development and I ask you to create an endpoint.&lt;br&gt;&lt;br&gt;
You need to:  &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;validate some input
&lt;/li&gt;
&lt;li&gt;query the database
&lt;/li&gt;
&lt;li&gt;handle errors
&lt;/li&gt;
&lt;li&gt;return the proper HTTP codes
&lt;/li&gt;
&lt;li&gt;write tests
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;A few years ago, you probably had to learn at least &lt;em&gt;something&lt;/em&gt; about each of those things to finish the task.  &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Maybe your SQL query was horrible and you learned about indexes because of it.
&lt;/li&gt;
&lt;li&gt;Maybe two requests modified the same thing and you discovered race conditions.
&lt;/li&gt;
&lt;li&gt;Maybe you returned 200 for literally everything because HTTP status codes were still a mystery to you (we've all been there), that’s the point where I learned about &lt;a href="https://httpcat.com" rel="noopener noreferrer"&gt;httpcat.com&lt;/a&gt; lol
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Today, you can ask an agent:&lt;br&gt;&lt;br&gt;
“Implement this endpoint following the patterns in this repository. Add validation and tests.”&lt;br&gt;&lt;br&gt;
And there's a pretty good chance it will do it correctly. The junior is now more productive. You are more productive. I am more productive. Everyone is happy.&lt;br&gt;&lt;br&gt;
But did you actually learn why the implementation is correct? That's a different question.  &lt;/p&gt;

&lt;p&gt;A &lt;a href="https://www.edtech.tum.de/the-dissociation-of-performance-and-learning-in-ai-supported-programming-education/" rel="noopener noreferrer"&gt;2026 study from the Technical University of Munich&lt;/a&gt; tested this with 275 programming students. Students using AI performed better on the programming tasks, but that improvement did &lt;strong&gt;not&lt;/strong&gt; translate into significantly better conceptual understanding compared with students using traditional resources.  &lt;/p&gt;

&lt;p&gt;This is interesting for one very important reason: we're getting better at producing the result, but not necessarily better at understanding how we got there. It’s like eating a frozen pizza: you ate a pizza, that’s great. But, &lt;em&gt;did you learn how to make a pizza&lt;/em&gt;?  &lt;/p&gt;

&lt;h2&gt;
  
  
  The boring stuff was useful
&lt;/h2&gt;

&lt;p&gt;The problem is that a lot of the annoying parts of learning programming were actually... learning. Spending two hours debugging something stupid sucks, reading documentation because Stack Overflow didn't have your exact answer (or they just threw rocks at you for asking a “dumb” question) sucks, writing a slow database query, discovering it's slow, understanding why and fixing it sucks.  &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;But you remember those things.&lt;/strong&gt;  &lt;/p&gt;

&lt;p&gt;I've said this before and I'll probably keep saying it until AI replaces me: &lt;strong&gt;You cannot prompt what you don't know exists.&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
And there's a second part to that: &lt;strong&gt;You cannot properly review what you don't understand.&lt;/strong&gt;  &lt;/p&gt;

&lt;p&gt;AI can generate a perfectly reasonable database query. But, *&lt;em&gt;how do you know it's going to murder your database when the table has 20 million rows?  *&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;AI can implement retries. But, &lt;strong&gt;how do you know retrying that specific operation can charge someone twice?&lt;/strong&gt;  &lt;/p&gt;

&lt;p&gt;AI can add caching. But, *&lt;em&gt;how do you know the thing you're caching should not be cached?  *&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;The answer is &lt;strong&gt;experience&lt;/strong&gt;. And experience usually comes from doing stuff, breaking stuff and sometimes wondering why the hell production is on fire. If we let AI remove too much of that process, _we may be removing part of the path that creates good engineers.  _&lt;/p&gt;

&lt;p&gt;There's already some evidence that this isn't only a programming thing. &lt;a href="https://www.microsoft.com/en-us/research/publication/the-impact-of-generative-ai-on-critical-thinking-self-reported-reductions-in-cognitive-effort-and-confidence-effects-from-a-survey-of-knowledge-workers/" rel="noopener noreferrer"&gt;Microsoft Research surveyed 319 knowledge workers about 936 real uses of generative AI&lt;/a&gt;. Higher confidence in AI was associated with less critical thinking effort, while people who were more confident in their own knowledge tended to think more critically about the result. Which makes sense. If you know the topic, &lt;strong&gt;AI is something you supervise&lt;/strong&gt;. If you don't, &lt;strong&gt;AI can easily become something you trust.&lt;/strong&gt;  &lt;/p&gt;

&lt;h2&gt;
  
  
  Ok, but they'll learn later... right?
&lt;/h2&gt;

&lt;p&gt;Maybe.&lt;/p&gt;

&lt;p&gt;But here's where things get more complicated. We're also starting to need fewer junior developers. &lt;a href="https://digitaleconomy.stanford.edu/publication/canaries-in-the-coal-mine-six-facts-about-the-recent-employment-effects-of-artificial-intelligence/?sck=e7755a74-2c92-4599-a31f-d8d04fefbda5%7Cf096abf9-83ca-444a-81b9-d203a2ca0198%7Cfb.1.1790640959475.835605%7C%7Ce7755a74-2c92-4599-a31f-d8d04fefbda5%7C62bb42b7-9eda-4c71-bab2-01af93fa1b00%7Cfb.1.1790640955539.1892144355%7C%7Ce7755a74-2c92-4599-a31f-d8d04fefbda5%7C074ce756-5ebe-442d-876a-eb74bb6841c8%7Cfb.1.1786822140828.566583304%7C" rel="noopener noreferrer"&gt;Stanford's Digital Economy Lab&lt;/a&gt; has been tracking employment in occupations exposed to AI using payroll data from millions of workers. Their August 2026 update found something pretty noticeable: employment for workers aged 22–25 in highly AI-exposed occupations was about &lt;strong&gt;19% below&lt;/strong&gt; where it would've been if it had followed the same trend as less-exposed occupations. More experienced workers did not show the same gap.  &lt;/p&gt;

&lt;p&gt;They also found that the difference seems to be coming mostly from &lt;strong&gt;reduced hiring&lt;/strong&gt;, not people getting fired. That doesn't mean "AI killed 19% of junior jobs". Labor markets are way more complicated than that and the researchers themselves don't claim that, but the direction is something to take a closer look.  &lt;/p&gt;

&lt;p&gt;Companies can give experienced developers AI tools and suddenly get a lot more output from them. So why hire five juniors when your existing team can now do more? Economically, that can make perfect sense. &lt;strong&gt;Until it doesn’t.&lt;/strong&gt;  &lt;/p&gt;

&lt;h2&gt;
  
  
  Where do seniors come from?
&lt;/h2&gt;

&lt;p&gt;This is the part I think we're not discussing enough, Senior developers don't spawn with 8 years of experience. Every senior was a junior. Even the ones you see on the web with thousands of followers or the ones that have created truly amazing stuff, they were juniors some day (except from the guy that wrote TempleOS, I think he received his knowledge by divine grace). Every staff engineer wrote stupid code. Every database expert probably created at least one query they're not particularly proud of. You become experienced by accumulating a ridiculous amount of small lessons over many years.  &lt;/p&gt;

&lt;p&gt;But imagine the direction we're heading:  &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Companies hire fewer juniors.
&lt;/li&gt;
&lt;li&gt;The juniors we hire skip more of the low-level work using AI.
&lt;/li&gt;
&lt;li&gt;Experienced developers become insanely productive using agents.
&lt;/li&gt;
&lt;li&gt;Companies need even fewer developers.
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Looks pretty good on an Excel sheet, then 10 years pass and someday you turn around and ask yourself: “Where are the new senior engineers?”. We could end up creating some kind of &lt;strong&gt;experience debt&lt;/strong&gt;. Similar to technical debt: you move faster today by borrowing from the future.  &lt;/p&gt;

&lt;p&gt;Except this time we're borrowing engineers.  &lt;/p&gt;

&lt;h2&gt;
  
  
  So... should juniors stop using AI?
&lt;/h2&gt;

&lt;p&gt;No. That would be dumb. AI is probably one of the best learning tools we've ever created. You have something available 24/7 that can explain a concept 20 times without getting tired of you.  &lt;/p&gt;

&lt;p&gt;Use it.  &lt;/p&gt;

&lt;p&gt;But there's a big difference between: “Build this for me” and “help me understand how to build this”.  &lt;/p&gt;

&lt;p&gt;There's also a difference between accepting the first implementation and asking: “What can go wrong here?” Or  “Why did you choose this approach?” Or even closing the AI for an hour and trying to solve the damn thing yourself.  &lt;/p&gt;

&lt;p&gt;We're not going back. AI is here, agents are getting better and software will probably continue becoming cheaper to produce, which is good, but we have to be careful not to optimize the learning out of learning, because in the future the problem may not be that there’s no longer a “programming” career, or that AI finally replaced everyone and now we have to adore Sam Altman for a living.   &lt;/p&gt;

&lt;p&gt;It might be that we have the most powerful tools available, the better models… but not enough people who actually understand what the hell is going on anymore.  &lt;/p&gt;

</description>
      <category>ai</category>
      <category>programming</category>
      <category>career</category>
      <category>beginners</category>
    </item>
    <item>
      <title>Gotta Earn 'Em All: The Gym Badges of Agentic Engineering (Part 2)</title>
      <dc:creator>Kevin Alemán</dc:creator>
      <pubDate>Fri, 03 Jul 2026 02:35:20 +0000</pubDate>
      <link>https://dev.to/kaleman15/gotta-earn-em-all-the-gym-badges-of-agentic-engineering-part-2-5a11</link>
      <guid>https://dev.to/kaleman15/gotta-earn-em-all-the-gym-badges-of-agentic-engineering-part-2-5a11</guid>
      <description>&lt;p&gt;Last time we earned four badges: bedrock, context, scoped speed, and the patience to garden instead of shaking a vending machine. If you missed it, it's linked above. The guard at the gate hasn't moved. But you did.&lt;/p&gt;

&lt;p&gt;Quick refresher if you're just walking in: by &lt;em&gt;"agentic engineering"&lt;/em&gt; I mean using AI agents like Claude Code or Copilot to build real software, not just tab-complete. And fair warning, one of today's badges comes with receipts. 211 million lines of code worth.&lt;/p&gt;

&lt;p&gt;The first four gyms give you the basics. Useful! But nobody becomes Champion by learning just the basics. Past Celadon the game changes: it stops being about doing the work and starts being about &lt;em&gt;not getting fooled by it.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Let's finish this.&lt;/p&gt;

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

&lt;h2&gt;
  
  
  Badge 5: Soul Badge: learn to taste poison
&lt;/h2&gt;

&lt;p&gt;Koga. Poison type. His gym is a maze of invisible walls, so you spend twenty minutes walking face-first into nothing while ninjas watch you. Foreshadowing.&lt;/p&gt;

&lt;p&gt;This might be THE badge of the agent era, and the hardest to teach. Not spotting code that's &lt;em&gt;wrong&lt;/em&gt;. Spotting code that's wrong while looking completely, beautifully right.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// looks done. runs. passes the demo.&lt;/span&gt;
&lt;span class="nx"&gt;users&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;forEach&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;sendNotification&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;All notifications sent!&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// what actually waits&lt;/span&gt;
&lt;span class="k"&gt;for &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;user&lt;/span&gt; &lt;span class="k"&gt;of&lt;/span&gt; &lt;span class="nx"&gt;users&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;sendNotification&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;All notifications sent!&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Every line in the first block is real, and the 3-user demo works. But &lt;code&gt;forEach&lt;/code&gt; ignores your &lt;code&gt;await&lt;/code&gt;: the log prints before a single notification goes out, and if one fails, the error evaporates into the void. Nothing is broken enough to fail. Everything is broken enough to hurt you in two weeks.&lt;/p&gt;

&lt;p&gt;That's what poison tastes like. Not bitter. Slightly, &lt;em&gt;slightly&lt;/em&gt; off.&lt;/p&gt;

&lt;p&gt;And you can't outsource the taste test: asking an LLM "is this slop?" can produce slop in the answer. Tasting is a human skill, and you earn it by having eaten some poison before. (Hello again, Badge 1.)&lt;/p&gt;

&lt;p&gt;If you can't tell legit from slightly-off, the agent is driving and you're asleep in the passenger seat. Don't offload your life to the agents. Control them. You are the human in charge.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fm1qfvtmsw3ztqgxspko6.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fm1qfvtmsw3ztqgxspko6.png" alt="Nintendo Pokemon Fire Red Sabrina Battle" width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  Badge 6: Marsh Badge: it's not telepathy
&lt;/h2&gt;

&lt;p&gt;At some point the agent finishes your thought, matches your style, and your brain quietly files it under "understands me."&lt;/p&gt;

&lt;p&gt;It doesn't. What actually happens when you get good is way less mystical: &lt;strong&gt;you build a mental model of how it screws up.&lt;/strong&gt; It invents APIs with total confidence. It knows nothing newer than its training. And it will happily agree with a wrong premise if you say it like you mean it:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// what most people send
"since the bug is in the cache layer, fix the cache invalidation"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// what you could be doing
"users report stale data after profile updates.
here's the request flow and the cache config.
where would YOU look first, and why?"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;State it with enough conviction and the agent will find you a bug in the cache, whether one lives there or not. Ask it to reason first and it suddenly can.&lt;/p&gt;

&lt;p&gt;Prompting is talking to a very smart coworker with amnesia about your project and a habit of bluffing. Internalize that and half your prompts fix themselves for free.&lt;/p&gt;

&lt;p&gt;There's plenty of "skills" that would help you on this matter. A few examples:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/multica-ai/andrej-karpathy-skills" rel="noopener noreferrer"&gt;https://github.com/multica-ai/andrej-karpathy-skills&lt;/a&gt;&lt;/p&gt;


&lt;div class="crayons-card c-embed text-styles text-styles--secondary"&gt;
    &lt;div class="c-embed__content"&gt;
        &lt;div class="c-embed__cover"&gt;
          &lt;a href="https://claude.com/marketplace/plugins/superpowers" class="c-link align-middle" rel="noopener noreferrer"&gt;
            &lt;img alt="" src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fassets.claude.com%2Ff66071070c4701ea2c37fc01b3c0f83623cf29d3.jpg%3Fw%3D2400%26h%3D1260%26fit%3Dcrop" height="1260" class="m-0" width="2400"&gt;
          &lt;/a&gt;
        &lt;/div&gt;
      &lt;div class="c-embed__body"&gt;
        &lt;h2 class="fs-xl lh-tight"&gt;
          &lt;a href="https://claude.com/marketplace/plugins/superpowers" rel="noopener noreferrer" class="c-link"&gt;
            Superpowers | Claude by Anthropic
          &lt;/a&gt;
        &lt;/h2&gt;
          &lt;p class="truncate-at-3"&gt;
            Claude learns brainstorming, subagent development with code review, debugging, TDD, and skill authoring through Superpowers.
          &lt;/p&gt;
        &lt;div class="color-secondary fs-s flex items-center"&gt;
            &lt;img alt="favicon" class="c-embed__favicon m-0 mr-2 radius-0" src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fassets.claude.com%2F95a868946ac8a31e5ff832e2899f294aa368b836.png%3Fw%3D32%26h%3D32" width="32" height="32"&gt;
          claude.com
        &lt;/div&gt;
      &lt;/div&gt;
    &lt;/div&gt;
&lt;/div&gt;



&lt;p&gt;Use them. They're not magic, they're frameworks. You can still produce bad things with them. But they'll help you not to shoot yourself in the foot too frequently.&lt;/p&gt;

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

&lt;h2&gt;
  
  
  Badge 7: Volcano Badge: the fire doesn't care who wrote the code
&lt;/h2&gt;

&lt;p&gt;Blaine makes you answer quiz questions before he'll even battle you. Which is just debugging with extra steps: you answer the riddles, then you get the fight.&lt;/p&gt;

&lt;p&gt;Generating code is the tutorial. This badge is everything &lt;em&gt;after&lt;/em&gt; it ships, when the thing the agent wrote is live and gently combusting at 2 AM. No clever prompt saves you here. You need logs you can actually read. Traces. The hard-won knowledge that one container's JSON log file can quietly eat a whole disk while you sleep (don't ask how I know. ok, ask, it was bad).&lt;/p&gt;

&lt;p&gt;Unlike the other badges, this one has a concrete training regime:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Make your logs readable before you need them.&lt;/strong&gt; Structured logs with request IDs, not &lt;code&gt;console.log("here 2")&lt;/code&gt;. Future-you at 2 AM is a dumber person. Write for him.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Learn one tracing tool.&lt;/strong&gt; Any. "Where did this request die" should be a query, not a vibe.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Read your own logs cold.&lt;/strong&gt; Trace one request end to end on a normal day. If you can't follow it when nothing's broken, you have zero chance when everything is.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Treat your agent as a coworker.&lt;/strong&gt; Share with it all the context you would share with a human: stack traces, logs, screenshots, etc. Anything that it can use to understand and help you investigate. That's very useful.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This also means you should &lt;em&gt;know your product&lt;/em&gt; even if you vibe coded it. If you don't, then when the fire happens and Claude is down (and that happens very often, recently) you will be alone with your thoughts, and with some code that you've never seen in your life...&lt;/p&gt;

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

&lt;h2&gt;
  
  
  Badge 8: Earth Badge: it's your name on the commit
&lt;/h2&gt;

&lt;p&gt;I said I wasn't explaining this one until we got here, so: Giovanni isn't just the eighth gym leader. He's the &lt;strong&gt;boss of Team Rocket.&lt;/strong&gt; You spend the whole game dismantling his operation, and the final badge, the one the guard is waiting for, gets handed to you by the villain himself.&lt;/p&gt;

&lt;p&gt;Kid-me thought that was a cool twist. Adult-me sees what the twist is actually saying. Think about what Team Rocket &lt;em&gt;is&lt;/em&gt;: they don't raise Pokémon, they steal them. Their entire philosophy is getting the power without doing the training. And Giovanni is living proof it works: he's rich, he's feared, he runs a whole city. The game puts him, of all people, between you and the League. The final obstacle isn't a stronger trainer. It's the successful guy offering you his way of doing things.&lt;/p&gt;

&lt;p&gt;That's why I call it a temptation. The final boss of agentic engineering isn't a gnarly bug. It's the shortcut philosophy, and it &lt;em&gt;visibly works&lt;/em&gt;, at least at first. Let the agent's judgment quietly replace yours. Ship volume because merging feels like progress. Paste 200 lines you didn't read because it looked right and it was late. Shipping unread agent output is stealing Pokémon instead of training them: same power on paper, none of it yours.&lt;/p&gt;

&lt;p&gt;And before you tell me this is a "skill issue" that only happens to juniors: the industry is drifting into it &lt;em&gt;at scale&lt;/em&gt;, and we have receipts. GitClear analyzed 211 million changed lines of code across five years. Duplicated code blocks jumped 8x in a single year. Copy/pasted lines exceeded refactored ("moved") lines for the first time in the dataset's history. Churn, the code you rewrite within two weeks of committing it because it wasn't right the first time, roughly doubled from its pre-AI baseline. And Google's own DORA report found delivery stability dropped 7.2% as AI adoption went up.&lt;/p&gt;

&lt;p&gt;You can watch the same movie at a single company. Spotify's VP of Engineering recently shared that they ship 4,500 production deploys a day, with 73% of PRs now AI-assisted. Genuinely impressive numbers. Meanwhile, their own community forums are an endless scroll of "the app gets slower and worse with every update," and the most viral reaction to those 4,500 deploys was someone asking what in the hell they're all &lt;em&gt;for&lt;/em&gt;, since the product barely feels different. I'm not saying the AI-assisted PRs caused the complaints, that would be lazy. I'm saying throughput went vertical and perceived quality didn't follow, and that's a problem.&lt;/p&gt;

&lt;p&gt;Sources, so you can check me. The 211M lines analysis:&lt;/p&gt;


&lt;div class="crayons-card c-embed text-styles text-styles--secondary"&gt;
    &lt;div class="c-embed__content"&gt;
      &lt;div class="c-embed__body flex items-center justify-between"&gt;
        &lt;a href="https://www.gitclear.com/ai_assistant_code_quality_2025_research" rel="noopener noreferrer" class="c-link fw-bold flex items-center"&gt;
          &lt;span class="mr-2"&gt;gitclear.com&lt;/span&gt;
          

        &lt;/a&gt;
      &lt;/div&gt;
    &lt;/div&gt;
&lt;/div&gt;


&lt;p&gt;DORA on delivery stability:&lt;/p&gt;


&lt;div class="crayons-card c-embed text-styles text-styles--secondary"&gt;
    &lt;div class="c-embed__content"&gt;
        &lt;div class="c-embed__cover"&gt;
          &lt;a href="https://dora.dev/research/2024/dora-report/" class="c-link align-middle" rel="noopener noreferrer"&gt;
            &lt;img alt="" src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdora.dev%2Fimg%2Fmisc%2Fdora_social_image.png" height="420" class="m-0" width="800"&gt;
          &lt;/a&gt;
        &lt;/div&gt;
      &lt;div class="c-embed__body"&gt;
        &lt;h2 class="fs-xl lh-tight"&gt;
          &lt;a href="https://dora.dev/research/2024/dora-report/" rel="noopener noreferrer" class="c-link"&gt;
            DORA | Accelerate State of DevOps Report 2024
          &lt;/a&gt;
        &lt;/h2&gt;
          &lt;p class="truncate-at-3"&gt;
            DORA is a long running research program that seeks to understand the capabilities that drive software delivery and operations performance. DORA helps teams apply those capabilities, leading to better organizational performance.
          &lt;/p&gt;
        &lt;div class="color-secondary fs-s flex items-center"&gt;
            &lt;img alt="favicon" class="c-embed__favicon m-0 mr-2 radius-0" src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdora.dev%2Ffavicon-32x32.png" width="39" height="39"&gt;
          dora.dev
        &lt;/div&gt;
      &lt;/div&gt;
    &lt;/div&gt;
&lt;/div&gt;


&lt;p&gt;Spotify's 4,500 deploys/day and 73% AI-assisted PRs + reaction:&lt;/p&gt;

&lt;p&gt;&lt;iframe class="tweet-embed" id="tweet-2071817938076860432-787" src="https://platform.twitter.com/embed/Tweet.html?id=2071817938076860432"&gt;
&lt;/iframe&gt;

  // Detect dark theme
  var iframe = document.getElementById('tweet-2071817938076860432-787');
  if (document.body.className.includes('dark-theme')) {
    iframe.src = "https://platform.twitter.com/embed/Tweet.html?id=2071817938076860432&amp;amp;theme=dark"
  }



&lt;/p&gt;

&lt;p&gt;Everyone is shipping faster. What's shipping is not clearly getting better. Nobody decided this. Millions of developers drifted into it, one skipped review at a time. That's what makes it the boss fight.&lt;/p&gt;

&lt;p&gt;The annoying fact that keeps you grounded: &lt;strong&gt;the agent doesn't own the PR. You do.&lt;/strong&gt; When it breaks, nobody opens a ticket against the model. Code is cheap now. Your name isn't.&lt;/p&gt;

&lt;h2&gt;
  
  
  Eight badges. Now what?
&lt;/h2&gt;

&lt;p&gt;The gate isn't the end. It's a new beginning. As everything in life, once you reached the summit, you realize it was one of many...&lt;/p&gt;

</description>
      <category>ai</category>
      <category>agents</category>
      <category>programming</category>
      <category>career</category>
    </item>
    <item>
      <title>The Apple Books data model</title>
      <dc:creator>Kevin Alemán</dc:creator>
      <pubDate>Mon, 22 Jun 2026 19:54:21 +0000</pubDate>
      <link>https://dev.to/kaleman15/the-apple-books-data-model-1f8h</link>
      <guid>https://dev.to/kaleman15/the-apple-books-data-model-1f8h</guid>
      <description>&lt;p&gt;Apple Books stores everything about your reading on disk, in plain SQLite. Your books, your highlights, your shelves, your ratings, the dates you finished things, all of it sits in a handful of databases you can open and query right now. The app surfaces only a fraction of it.&lt;/p&gt;

&lt;p&gt;This is a reference for that data model: where it lives, the conventions it follows, the entities that matter, and, most importantly, how those entities connect. The relationships are the interesting part. A single table is just a list; the model is the set of links between tables, and Apple Books has three distinct relationship patterns worth understanding.&lt;/p&gt;

&lt;p&gt;Everything below is observable on any Mac with Books installed. No private APIs, no entitlements, just SQLite.&lt;/p&gt;

&lt;h2&gt;
  
  
  Storage layout
&lt;/h2&gt;

&lt;p&gt;Sandboxed macOS apps keep their data under &lt;code&gt;~/Library/Containers&lt;/code&gt;. Apple Books spreads its across a few SQLite files in two containers:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;~/Library/Containers/com.apple.iBooksX/Data/Documents/
├── BKLibrary/
│   └── BKLibrary-1-091020131601.sqlite           # the library: one row per book
├── AEAnnotation/
│   └── AEAnnotation_v10312011_1727_local.sqlite  # highlights and notes
└── BCRecentlyOpenedBooksDB/
    └── BCRecentlyOpenedBooksDB.sqlite            # recently-opened events
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The numeric suffixes in the filenames are not stable across installs, so match on the prefix (&lt;code&gt;BKLibrary-1-*.sqlite&lt;/code&gt;) rather than hardcoding the full name.&lt;/p&gt;

&lt;h2&gt;
  
  
  Core Data conventions
&lt;/h2&gt;

&lt;p&gt;Every table and column is uppercase and prefixed with &lt;code&gt;Z&lt;/code&gt;: &lt;code&gt;ZBKLIBRARYASSET&lt;/code&gt;, &lt;code&gt;ZTITLE&lt;/code&gt;, &lt;code&gt;ZANNOTATIONASSETID&lt;/code&gt;. That prefix is the signature of &lt;strong&gt;Core Data&lt;/strong&gt;, Apple's persistence framework, which generates the SQLite schema underneath. Recognizing it tells you what to expect:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;Z_PK&lt;/code&gt; — integer primary key on every entity table.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;Z_ENT&lt;/code&gt; — which entity (table) a row belongs to.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;Z_OPT&lt;/code&gt; — Core Data's optimistic-locking version counter.&lt;/li&gt;
&lt;li&gt;Application columns carry the &lt;code&gt;Z&lt;/code&gt; prefix too (&lt;code&gt;ZTITLE&lt;/code&gt;, &lt;code&gt;ZRATING&lt;/code&gt;, ...).&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Two quirks follow from this that affect almost every query:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Booleans are nullable.&lt;/strong&gt; Flags like &lt;code&gt;ZISFINISHED&lt;/code&gt; are &lt;code&gt;1&lt;/code&gt; or &lt;code&gt;NULL&lt;/code&gt;, not &lt;code&gt;1&lt;/code&gt; or &lt;code&gt;0&lt;/code&gt;. &lt;code&gt;WHERE ZISFINISHED = 0&lt;/code&gt; matches nothing. Use &lt;code&gt;IS NULL&lt;/code&gt; / &lt;code&gt;!= 1&lt;/code&gt; for the negative case.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Timestamps use a 2001 epoch.&lt;/strong&gt; Core Data counts seconds from &lt;code&gt;2001-01-01&lt;/code&gt;, not the Unix &lt;code&gt;1970-01-01&lt;/code&gt;. The two differ by exactly &lt;code&gt;978307200&lt;/code&gt; seconds. To read any date column as a real date:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;SELECT&lt;/span&gt; &lt;span class="nb"&gt;date&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ZDATEFINISHED&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;978307200&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'unixepoch'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="n"&gt;ZBKLIBRARYASSET&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="c1"&gt;-- 2026-05-16&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Every date column in every one of these databases uses the same offset.&lt;/p&gt;

&lt;h2&gt;
  
  
  Reading the files safely
&lt;/h2&gt;

&lt;p&gt;Books keeps these databases open in &lt;strong&gt;WAL mode&lt;/strong&gt; (Write-Ahead Logging). Recent changes live in &lt;code&gt;-wal&lt;/code&gt; and &lt;code&gt;-shm&lt;/code&gt; sidecar files next to the main &lt;code&gt;.sqlite&lt;/code&gt; and have not yet been checkpointed into it. Opening the main file directly while Books is running yields stale reads or lock errors.&lt;/p&gt;

&lt;p&gt;The safe approach for read-only analysis is to copy the database &lt;strong&gt;and its sidecars&lt;/strong&gt; to a scratch location, then open the copy read-only:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;BKLibrary-1-...sqlite      →  copy
BKLibrary-1-...sqlite-wal  →  copy   (must travel together)
BKLibrary-1-...sqlite-shm  →  copy
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;SQLite reconstructs the current state from the copied set, and the originals are never touched.&lt;/p&gt;

&lt;h2&gt;
  
  
  The central entity: ZBKLIBRARYASSET
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;ZBKLIBRARYASSET&lt;/code&gt; is the hub of the model: one row per item in your library, and the table nearly everything else links back to. It has over a hundred columns; these are the ones that carry meaning:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Column&lt;/th&gt;
&lt;th&gt;Meaning&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;ZASSETID&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;stable identifier for the book — the join key for the entire model&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;code&gt;ZTITLE&lt;/code&gt;, &lt;code&gt;ZAUTHOR&lt;/code&gt;, &lt;code&gt;ZGENRE&lt;/code&gt;, &lt;code&gt;ZLANGUAGE&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;descriptive metadata&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;code&gt;ZPAGECOUNT&lt;/code&gt;, &lt;code&gt;ZREADINGPROGRESS&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;length, and progress as a 0–1 float&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;code&gt;ZISFINISHED&lt;/code&gt;, &lt;code&gt;ZDATEFINISHED&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;completion flag (1/NULL) and date&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;ZRATING&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;user star rating; &lt;code&gt;0&lt;/code&gt; means unrated&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;code&gt;ZPURCHASEDATE&lt;/code&gt;, &lt;code&gt;ZLASTENGAGEDDATE&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;acquisition and last-interaction timestamps&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;ZCONTENTTYPE&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;format/role of the row (see the series section)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;code&gt;ZSERIESID&lt;/code&gt;, &lt;code&gt;ZSERIESNEXTFLAG&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;series membership and "next up" marker&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;ZDURATION&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;runtime in seconds for audiobooks (&lt;code&gt;0&lt;/code&gt; otherwise)&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;A baseline query, books finished:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;SELECT&lt;/span&gt; &lt;span class="k"&gt;count&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="n"&gt;ZBKLIBRARYASSET&lt;/span&gt; &lt;span class="k"&gt;WHERE&lt;/span&gt; &lt;span class="n"&gt;ZISFINISHED&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;ZASSETID&lt;/code&gt; is the thread that runs through the whole model. Hold onto it.&lt;/p&gt;

&lt;h2&gt;
  
  
  The relationships
&lt;/h2&gt;

&lt;p&gt;Three relationships connect to &lt;code&gt;ZBKLIBRARYASSET&lt;/code&gt;, and each uses a different structural pattern: a cross-database join, a junction table, and a self-join.&lt;/p&gt;

&lt;h3&gt;
  
  
  1. Highlights — a cross-database relationship
&lt;/h3&gt;

&lt;p&gt;Highlights and notes are not stored with the books. They live in a separate database, &lt;code&gt;AEAnnotation&lt;/code&gt;, in the table &lt;code&gt;ZAEANNOTATION&lt;/code&gt;. Each row is one annotation:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Column&lt;/th&gt;
&lt;th&gt;Meaning&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;ZANNOTATIONASSETID&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;foreign key to the book&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;ZANNOTATIONSELECTEDTEXT&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;the highlighted text&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;ZANNOTATIONNOTE&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;attached note, if any&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;ZANNOTATIONSTYLE&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;highlight color, &lt;code&gt;0&lt;/code&gt;–&lt;code&gt;5&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;ZANNOTATIONDELETED&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;soft-delete flag — filter &lt;code&gt;= 0&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;The link is &lt;code&gt;ZANNOTATIONASSETID&lt;/code&gt;, and the non-obvious detail is which library column it targets. It is &lt;strong&gt;not&lt;/strong&gt; &lt;code&gt;ZEPUBID&lt;/code&gt;; it matches &lt;code&gt;ZASSETID&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;ZBKLIBRARYASSET.ZASSETID  ──1:N──  ZAEANNOTATION.ZANNOTATIONASSETID
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Because the two tables live in different files, the join requires attaching one database to the other first. SQLite's &lt;code&gt;ATTACH&lt;/code&gt; makes them queryable as one:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="n"&gt;ATTACH&lt;/span&gt; &lt;span class="k"&gt;DATABASE&lt;/span&gt; &lt;span class="s1"&gt;'annotations.sqlite'&lt;/span&gt; &lt;span class="k"&gt;AS&lt;/span&gt; &lt;span class="n"&gt;ann&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;SELECT&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ZTITLE&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;count&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;AS&lt;/span&gt; &lt;span class="n"&gt;highlights&lt;/span&gt;
&lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="n"&gt;ann&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ZAEANNOTATION&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt;
&lt;span class="k"&gt;JOIN&lt;/span&gt; &lt;span class="n"&gt;ZBKLIBRARYASSET&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt; &lt;span class="k"&gt;ON&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ZASSETID&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ZANNOTATIONASSETID&lt;/span&gt;
&lt;span class="k"&gt;WHERE&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ZANNOTATIONDELETED&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;
  &lt;span class="k"&gt;AND&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ZANNOTATIONSELECTEDTEXT&lt;/span&gt; &lt;span class="k"&gt;IS&lt;/span&gt; &lt;span class="k"&gt;NOT&lt;/span&gt; &lt;span class="k"&gt;NULL&lt;/span&gt;
&lt;span class="k"&gt;GROUP&lt;/span&gt; &lt;span class="k"&gt;BY&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ZTITLE&lt;/span&gt;
&lt;span class="k"&gt;ORDER&lt;/span&gt; &lt;span class="k"&gt;BY&lt;/span&gt; &lt;span class="n"&gt;highlights&lt;/span&gt; &lt;span class="k"&gt;DESC&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Become an Effective Software Engineering Manager | 404
La Atalaya, marzo de 2026                        |  53
The Midnight Library: A Novel                    |  25
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  2. Shelves — a many-to-many via junction table
&lt;/h3&gt;

&lt;p&gt;Collections (&lt;em&gt;Want to Read&lt;/em&gt;, &lt;em&gt;Finished&lt;/em&gt;, and custom shelves) are a many-to-many relationship: a book can belong to several collections, and a collection holds many books. Core Data models this with a junction table in the middle.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;ZBKCOLLECTION           ZBKCOLLECTIONMEMBER          ZBKLIBRARYASSET
  Z_PK   ◄──────────────  ZCOLLECTION                     ZASSETID
  ZTITLE                   ZASSETID  ─────────────────────────►
                           ZSORTKEY
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;ZBKCOLLECTIONMEMBER&lt;/code&gt; holds one row per membership, pointing both ways: &lt;code&gt;ZCOLLECTION&lt;/code&gt; references the collection's &lt;code&gt;Z_PK&lt;/code&gt;, and &lt;code&gt;ZASSETID&lt;/code&gt; references the book. Listing the contents of a named shelf means traversing the junction:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;SELECT&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ZTITLE&lt;/span&gt;
&lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="n"&gt;ZBKCOLLECTIONMEMBER&lt;/span&gt; &lt;span class="n"&gt;m&lt;/span&gt;
&lt;span class="k"&gt;JOIN&lt;/span&gt; &lt;span class="n"&gt;ZBKCOLLECTION&lt;/span&gt; &lt;span class="k"&gt;c&lt;/span&gt;   &lt;span class="k"&gt;ON&lt;/span&gt; &lt;span class="k"&gt;c&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Z_PK&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;m&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ZCOLLECTION&lt;/span&gt;
&lt;span class="k"&gt;JOIN&lt;/span&gt; &lt;span class="n"&gt;ZBKLIBRARYASSET&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt; &lt;span class="k"&gt;ON&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ZASSETID&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;m&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ZASSETID&lt;/span&gt;
&lt;span class="k"&gt;WHERE&lt;/span&gt; &lt;span class="k"&gt;c&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ZTITLE&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'Want to Read'&lt;/span&gt;
&lt;span class="k"&gt;ORDER&lt;/span&gt; &lt;span class="k"&gt;BY&lt;/span&gt; &lt;span class="n"&gt;m&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ZSORTKEY&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  3. Series — a self-join with a container row
&lt;/h3&gt;

&lt;p&gt;Series have no dedicated table. Instead, two things encode them inside &lt;code&gt;ZBKLIBRARYASSET&lt;/code&gt; itself:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Every book in a series carries a shared &lt;code&gt;ZSERIESID&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;The series itself is a &lt;strong&gt;placeholder row in the same table&lt;/strong&gt;, identified by &lt;code&gt;ZCONTENTTYPE = 5&lt;/code&gt;. It stores the series' name and metadata but is not a readable book.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Reporting on a series therefore means joining &lt;code&gt;ZBKLIBRARYASSET&lt;/code&gt; to itself: the real members on one side, the container row on the other, matched on &lt;code&gt;ZSERIESID&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;SELECT&lt;/span&gt;
  &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;SELECT&lt;/span&gt; &lt;span class="k"&gt;c&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ZTITLE&lt;/span&gt; &lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="n"&gt;ZBKLIBRARYASSET&lt;/span&gt; &lt;span class="k"&gt;c&lt;/span&gt;
     &lt;span class="k"&gt;WHERE&lt;/span&gt; &lt;span class="k"&gt;c&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ZSERIESID&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;m&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ZSERIESID&lt;/span&gt; &lt;span class="k"&gt;AND&lt;/span&gt; &lt;span class="k"&gt;c&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ZCONTENTTYPE&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt; &lt;span class="k"&gt;LIMIT&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;AS&lt;/span&gt; &lt;span class="n"&gt;series&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="k"&gt;count&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;                                           &lt;span class="k"&gt;AS&lt;/span&gt; &lt;span class="n"&gt;total&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="k"&gt;sum&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;CASE&lt;/span&gt; &lt;span class="k"&gt;WHEN&lt;/span&gt; &lt;span class="n"&gt;m&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ZISFINISHED&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="k"&gt;THEN&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="k"&gt;ELSE&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="k"&gt;END&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;AS&lt;/span&gt; &lt;span class="k"&gt;read&lt;/span&gt;
&lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="n"&gt;ZBKLIBRARYASSET&lt;/span&gt; &lt;span class="n"&gt;m&lt;/span&gt;
&lt;span class="k"&gt;WHERE&lt;/span&gt; &lt;span class="n"&gt;m&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ZSERIESID&lt;/span&gt; &lt;span class="k"&gt;IS&lt;/span&gt; &lt;span class="k"&gt;NOT&lt;/span&gt; &lt;span class="k"&gt;NULL&lt;/span&gt; &lt;span class="k"&gt;AND&lt;/span&gt; &lt;span class="n"&gt;m&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ZCONTENTTYPE&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;
&lt;span class="k"&gt;GROUP&lt;/span&gt; &lt;span class="k"&gt;BY&lt;/span&gt; &lt;span class="n"&gt;m&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ZSERIESID&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;ZCONTENTTYPE != 5&lt;/code&gt; predicate matters beyond this query. The container row counts as a row in the table, so any aggregate over books, totals, format breakdowns, library size, must exclude type &lt;code&gt;5&lt;/code&gt; or it will overcount by one per series.&lt;/p&gt;

&lt;h2&gt;
  
  
  The model at a glance
&lt;/h2&gt;

&lt;p&gt;The three relationships form one compact graph, all anchored on &lt;code&gt;ZASSETID&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;                    ┌─────────────────────┐
   highlights ──────┤                     ├────── shelves
ZAEANNOTATION       │   ZBKLIBRARYASSET   │   ZBKCOLLECTION
(separate DB,       │      (ZASSETID)     │   via junction table
 ATTACH + JOIN)     │                     │   ZBKCOLLECTIONMEMBER
                    └──────────┬──────────┘
                               │ self-join on ZSERIESID
                               │ (container row, ZCONTENTTYPE = 5)
                            series
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;One central entity, three patterns: a cross-database join for annotations, a junction table for collections, a self-join for series. Most questions about a reading library reduce to one of these traversals.&lt;/p&gt;

&lt;h2&gt;
  
  
  A documented limitation: reading sessions
&lt;/h2&gt;

&lt;p&gt;The third database, &lt;code&gt;BCRecentlyOpenedBooksDB&lt;/code&gt;, contains &lt;code&gt;ZBCASSETREADINGSESSION&lt;/code&gt;, with &lt;code&gt;ZTIMEOPENED&lt;/code&gt; and &lt;code&gt;ZTIMECLOSED&lt;/code&gt; columns that look like they record reading duration. They do not.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;opened                | closed               | duration
2026-06-10 17:49:29   | 2026-06-10 17:49:33  | 4 seconds
2026-05-05 14:53:33   | 2026-05-05 14:53:56  | 22 seconds
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Each session spans a few seconds (an open event, not a reading span), &lt;code&gt;ZTIMEUPDATED&lt;/code&gt; is empty, and only the most recent handful of rows are retained. Actual time-spent-reading is not persisted and cannot be reconstructed from this data. The open &lt;em&gt;timestamps&lt;/em&gt; are valid, so they can support an opened-on-this-day signal, but not minutes-read.&lt;/p&gt;

&lt;h2&gt;
  
  
  Querying your own library
&lt;/h2&gt;

&lt;p&gt;None of this requires special tooling. On any Mac with Books:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;sqlite3 ~/Library/Containers/com.apple.iBooksX/Data/Documents/BKLibrary/BKLibrary-1-&lt;span class="k"&gt;*&lt;/span&gt;.sqlite &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="s2"&gt;"SELECT ZTITLE, ZAUTHOR FROM ZBKLIBRARYASSET WHERE ZISFINISHED = 1;"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;From there, the rest of the model is reachable by following &lt;code&gt;ZASSETID&lt;/code&gt;: attach the annotation database for highlights, walk &lt;code&gt;ZBKCOLLECTIONMEMBER&lt;/code&gt; for shelves, self-join on &lt;code&gt;ZSERIESID&lt;/code&gt; for series. The recurring practicalities are the same throughout: recognize the Core Data prefix, add &lt;code&gt;978307200&lt;/code&gt; to every timestamp, treat boolean flags as nullable, and exclude &lt;code&gt;ZCONTENTTYPE = 5&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Appendix: a reference implementation
&lt;/h2&gt;

&lt;p&gt;To exercise the model end to end, I built &lt;strong&gt;ReadStats&lt;/strong&gt;, a small macOS menu-bar app that reads these databases (read-only, via the copy-with-sidecars approach above) and renders the stats they imply: finished-per-year, currently-reading progress, the want-to-read backlog, stalled books, highlight counts and colors, series progress, and a searchable browser over every highlight.&lt;/p&gt;

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

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

&lt;p&gt;Each view in it is, underneath, one of the queries from this document. The library catalog is &lt;code&gt;ZBKLIBRARYASSET&lt;/code&gt;; the "most highlighted" list is the cross-database join; the backlog is the junction-table traversal; the series card is the self-join. The data model did the hard part. The app is mostly presentation on top of these relationships.&lt;/p&gt;

&lt;p&gt;If it's useful as a worked example of mapping a Core Data SQLite schema into a typed domain model, that's the part worth borrowing.&lt;/p&gt;

&lt;p&gt;The official disclaimer is that the whole discovery was assisted by Claude. Pretty fun stuff checking the databases and how they connect to each other and being able to re-present the information in a nice way.&lt;/p&gt;

</description>
      <category>macos</category>
      <category>sqlite</category>
      <category>programming</category>
      <category>database</category>
    </item>
    <item>
      <title>What are your most liked agent skills?</title>
      <dc:creator>Kevin Alemán</dc:creator>
      <pubDate>Fri, 19 Jun 2026 14:41:59 +0000</pubDate>
      <link>https://dev.to/kaleman15/what-are-your-most-liked-agent-skills-1d0f</link>
      <guid>https://dev.to/kaleman15/what-are-your-most-liked-agent-skills-1d0f</guid>
      <description>&lt;p&gt;An space for sharing your go-to agent skills so everyone can use them.&lt;/p&gt;

&lt;p&gt;My list:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Superpowers (planning &amp;amp; implementation)&lt;/li&gt;
&lt;li&gt;Caveman (for reducing token usage)&lt;/li&gt;
&lt;li&gt;Frontend Design (to help with styling)&lt;/li&gt;
&lt;li&gt;Remember (memory)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I have one i created myself called &lt;code&gt;teachme&lt;/code&gt;, which uses a bit of thinking to explain topics to you and then it evaluates your understanding.&lt;/p&gt;

&lt;p&gt;:)&lt;/p&gt;

</description>
      <category>discuss</category>
      <category>ai</category>
      <category>programming</category>
    </item>
    <item>
      <title>Gotta Earn 'Em All: The Gym Badges of Agentic Engineering (Part 1)</title>
      <dc:creator>Kevin Alemán</dc:creator>
      <pubDate>Wed, 17 Jun 2026 20:13:57 +0000</pubDate>
      <link>https://dev.to/kaleman15/gotta-earn-em-all-the-gym-badges-of-agentic-engineering-part-1-5bff</link>
      <guid>https://dev.to/kaleman15/gotta-earn-em-all-the-gym-badges-of-agentic-engineering-part-1-5bff</guid>
      <description>&lt;p&gt;There's a guy who stands at the entrance to the Indigo Plateau and will not let you through. Level 80 Charizard? Doesn't care. Seven gym badges pinned to your jacket? Come back when it's eight. No matter what you do, he won't let you pass until you meet the prerequisites.&lt;/p&gt;

&lt;p&gt;Kid-me thought he was the single most pointless NPC ever programmed. I wanted to go right to the action, not spending 5 hours to get all the badges. Replaying FireRed last month (the GOAT, don't @ me) I finally got what he's for. He isn't guarding the fun part. He's making sure that by the time you face the four people who can actually beat you, you've already survived the eight boring things that made you ready for them.&lt;/p&gt;

&lt;p&gt;Which is, more or less, my entire complaint about how we're using agents right now.&lt;/p&gt;

&lt;p&gt;Everybody wants to fight the Elite Four on day one. "I'll let the agent build the whole feature." "I'll let it refactor the repo while I grab a coffee." "I'll point Claude Code at the thing and vibe." And sometimes it works! Right up until it doesn't, and you genuinely cannot say &lt;em&gt;why&lt;/em&gt; because there were eight gyms between you and that gate and you strolled past every one.&lt;/p&gt;

&lt;p&gt;So here's the case, the way a Game Boy made it to me: before you're actually good with agents, there are badges to earn. Not tools to install, &lt;em&gt;things you have to know.&lt;/em&gt; Let's go gym by gym.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fkof97yqrvc9dgr53ha0s.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fkof97yqrvc9dgr53ha0s.png" alt="Nintendo Pokemon Fire Red Brock Battle" width="686" height="386"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Badge 1: Boulder Badge: rock before copilot
&lt;/h2&gt;

&lt;p&gt;Brock. Rock type. The first gym. The place where you thought choosing charmander was a bad call (until you trained enough and it learned Metal Claw which helps a little bit).&lt;/p&gt;

&lt;p&gt;This is the badge of knowing how to code &lt;em&gt;without&lt;/em&gt; the agent holding your hand. The foundations.&lt;/p&gt;

&lt;p&gt;I've said this before and I'll keep saying it until they revoke my keyboard: &lt;strong&gt;you cannot prompt what you don't know exists.&lt;/strong&gt; If you don't know your project just changed a function's typings, you won't tell the agent, you won't catch it when it gets it wrong, and you'll merrily ship something that &lt;em&gt;looks&lt;/em&gt; right and isn't. The agent didn't fail there. You showed up to the gym with no Pokémon.&lt;/p&gt;

&lt;p&gt;You don't need to know &lt;em&gt;everything&lt;/em&gt;. You need bedrock. Otherwise every badge after this one is built on sand and you're gonna have a bad time.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ff6xzkd46wcpk757aj1jk.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ff6xzkd46wcpk757aj1jk.png" alt="Nintendo Pokemon Fire Red Misty Battle" width="756" height="360"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Badge 2: Cascade Badge: the agent only knows what you pour in
&lt;/h2&gt;

&lt;p&gt;Water flows, context flows, you see where I'm going. An agent isn't psychic (we'll get to that gym), it knows &lt;em&gt;exactly&lt;/em&gt; what's in its context window and nothing else. Not your repo's weird conventions. Not the thing your team decided in Slack last Tuesday. Not the landmine that lives rent-free in one senior dev's brain.&lt;/p&gt;

&lt;p&gt;Look at these two and tell me they're getting the same result:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// what most people send
"fix the bug in the user evaluation"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// what you could be doing
"In src/users/evaluate.ts we hardcoded a company name to hit a deadline.
Now we ALSO need to exclude new users from company "bla",
WITHOUT touching how "fancy company" users get evaluated.
Here's the file, here's the test that has to stay green,
here's how we name things."
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Same model. The first one is basically throwing a Poké Ball at a wall. The second one is, you know, &lt;em&gt;engineering.&lt;/em&gt; Pour the context on purpose and everything downstream gets less cursed.&lt;/p&gt;

&lt;p&gt;Don't make your agent drink from a puddle.&lt;/p&gt;

&lt;p&gt;There's some cool skills that can make your agent "think" this way, but you have to think that way too, so both agent &amp;amp; you can work together on solving &amp;amp; creating.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F94wqmxb7jd54nkdgp4xp.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F94wqmxb7jd54nkdgp4xp.png" alt="Nintendo Pokemon Fire Red LT Surge Battle" width="800" height="381"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Badge 3: Thunder Badge: fast is a trap
&lt;/h2&gt;

&lt;p&gt;Here's what nobody warns you about: agents are &lt;em&gt;fast.&lt;/em&gt; Stupid fast. Faster than you. Faster than me. Faster than anything likely. Issues that would take me a week to solve an agent can find a probable cause in minutes. And speed multiplies whatever you give it, your galaxy-brain ideas and your dumbest ones, at the exact same voltage.&lt;/p&gt;

&lt;p&gt;I've ranted about this in open-source land: opening a PR now costs basically nothing, but &lt;em&gt;reviewing&lt;/em&gt; one still costs a human their actual time and sanity. That gap is a denial-of-service attack wearing a trenchcoat. You tell the agent "do this for every file!!" and now there are 100 changes, some great, some radioactive, and you have to read all 100 because the agent will not tell you which is which. Congrats, you DoS'd yourself.&lt;/p&gt;

&lt;p&gt;The badge here is learning to &lt;em&gt;not grab the lightning with both hands.&lt;/em&gt; Small tasks. Bounded scope. One thing at a time. A fast wrong answer isn't a head start, it just got to being wrong sooner. :(&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fj333vj5pfhqhhb6jx8ce.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fj333vj5pfhqhhb6jx8ce.png" alt="Nintendo Pokemon Fire Red Erika Battle" width="756" height="360"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Badge 4: Rainbow Badge: it's gardening, not a vending machine
&lt;/h2&gt;

&lt;p&gt;People treat agents like a vending machine: insert prompt, slot opens, finished feature falls out. Nope. It's &lt;em&gt;gardening.&lt;/em&gt; You plant a thing, you look at the weird mutant that grew, you prune the cursed branches, you re-prompt, you prune again. Repeat until it's a plant and not a crime scene.&lt;/p&gt;

&lt;p&gt;The first output is never the deliverable. It's a sprout. "Good, keep this shape, but the data layer is wrong, redo that part" is the actual loop. The people who look like wizards with agents aren't great prompters, they're patient gardeners who aren't precious about yeeting a bad draft into the sun.&lt;/p&gt;

&lt;p&gt;Plant small, prune often, be responsible for what your agent produces cause that's your personal image too.&lt;/p&gt;

&lt;h2&gt;
  
  
  Halfway to the League
&lt;/h2&gt;

&lt;p&gt;Four badges down. If you actually have these: bedrock, context, scoped speed, and the patience to garden instead of treating the agent like a vending machine, you're already ahead of most people loudly pretending to be good at this.&lt;/p&gt;

&lt;p&gt;Learning is a journey. Enjoy it. Don't let agents &amp;amp; AI remove from you the better part of programming: you getting better at it.&lt;/p&gt;

&lt;p&gt;Obviously, life is not Pokemon. You could perfectly bypass all of this and go straight into your terminal right now to get a "product". That's acceptable in some cases.&lt;/p&gt;

&lt;p&gt;But... where's the fun in that?&lt;/p&gt;

</description>
      <category>ai</category>
      <category>agents</category>
      <category>programming</category>
      <category>career</category>
    </item>
    <item>
      <title>You got selected for GSoC 2026, now what?</title>
      <dc:creator>Kevin Alemán</dc:creator>
      <pubDate>Mon, 04 May 2026 04:35:06 +0000</pubDate>
      <link>https://dev.to/kaleman15/you-got-selected-for-gsoc-2026-now-what-1bdc</link>
      <guid>https://dev.to/kaleman15/you-got-selected-for-gsoc-2026-now-what-1bdc</guid>
      <description>&lt;p&gt;So your inbox lit up yesterday with the email. The proposal worked, the interviews worked, the late-night drafts worked. Take a moment, breathe, tell your family, post the screenshot. You earned it 🎉&lt;br&gt;
Now, the actual fun part begins.&lt;/p&gt;

&lt;p&gt;GSoC is, at its core, a few months of getting paid to learn from people who have spent years figuring out how to build software that thousands (sometimes millions) of strangers depend on. Think of it as an internship, but instead of a single company, your "office" is the entire open source world, and your "coworkers" are engineers who chose to spend their free time making things better for everyone. That's a rare seat at the table. Don't waste it.&lt;/p&gt;

&lt;p&gt;Here are a few things to keep in mind so you make the most of it.&lt;/p&gt;
&lt;h2&gt;
  
  
  What a mentor looks for from you
&lt;/h2&gt;
&lt;h3&gt;
  
  
  They want to mentor, not babysit.
&lt;/h3&gt;

&lt;p&gt;Mentors signed up to guide you, answer the hard questions, and unblock you when the codebase fights back. What they did not sign up for is reading the README on your behalf. The heavy lifting, exploring the codebase, running it locally, breaking it, fixing it, writing code that smells like the rest of the repo, that's on you. &lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;A good rule: if you can find the answer in 30 minutes of digging, dig. If you've dug for two hours and you're more confused than when you started, ping them.&lt;/p&gt;

&lt;p&gt;Note 2: at Rocket.Chat, we have an internal meme called &lt;code&gt;:call-the-police:&lt;/code&gt; that would fit perfectly above. Sadly, due to GDPR and other international laws, I cannot share above. End of the note.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3&gt;
  
  
  Honesty is everything.
&lt;/h3&gt;

&lt;p&gt;LLMs are great at giving you &lt;em&gt;an answer&lt;/em&gt;. They're not great at giving you the answer for this specific repo, with this specific history, with that one weird workaround that's there because of a bug from 2019 nobody wants to revisit. When you step into that kind of fog, just say so. &lt;strong&gt;Mentors respect "I don't get why this is here" way more than a confident wrong guess&lt;/strong&gt;. That said, don't ask for permission to breathe. There's a middle ground between "I'm stuck on every line" and "I haven't said anything in two weeks", and that's where you want to live.&lt;/p&gt;
&lt;h3&gt;
  
  
  Let git do some of the talking.
&lt;/h3&gt;

&lt;p&gt;In a lot of open source repos, the git history is the real diary of the project. Match the style: if they squash, you squash; if they write essays in commit messages, you do too. &lt;strong&gt;Use commits as a steady drumbeat of progress, and save your mentor's inbox for the moments that actually need a human&lt;/strong&gt;. Adding a translation? That's a commit. Untangling a nasty bug and finding a creative fix? That's worth a "hey, look at this" message.&lt;/p&gt;
&lt;h2&gt;
  
  
  What you can ask from your mentor
&lt;/h2&gt;
&lt;h3&gt;
  
  
  Treat them like human documentation.
&lt;/h3&gt;

&lt;p&gt;Mentors are walking archives. They know why a function is named weirdly, which refactor everyone is afraid to touch, and that one PR from 2021 that explains everything. Tap into that, but don't drain the well. Try to find the answer yourself first, give it a responsible amount of time, and if you're still spinning, ask. &lt;strong&gt;The deadline is fixed&lt;/strong&gt;, and running in circles is the most expensive thing you can do with your summer.&lt;/p&gt;
&lt;h3&gt;
  
  
  Ask about the politics the proposal couldn't see.
&lt;/h3&gt;

&lt;p&gt;When you wrote the proposal, you were looking at the project from the outside. Now you're inside, and you'll start spotting things: tech debt, weird coupling, decisions that look wrong until someone explains they're load-bearing. Bring those up. Sometimes the answer will be "yes, let's fix it as part of your work." Other times it'll be "leave it, that rabbit hole eats summers." &lt;em&gt;Both are useful answers, and only your mentor can give them to you.&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  How to deliver on the proposal you already submitted
&lt;/h2&gt;
&lt;h3&gt;
  
  
  The proposal is the map, not the territory.
&lt;/h3&gt;

&lt;p&gt;You can't redraw it: the timeline, the deliverables, the headline goals are pretty much locked. But there's plenty of room inside the lines: code style, data shapes, security choices, edge cases, testing strategy. &lt;strong&gt;Talk those out with your mentor early&lt;/strong&gt;. The earlier the better, because rework in week 10 hurts a lot more than rework in week 2.&lt;/p&gt;
&lt;h3&gt;
  
  
  Once you've aligned, write a plan.
&lt;/h3&gt;

&lt;p&gt;Break the proposal into weekly chunks, with a rough idea of what "done" looks like for each one. Then, and this is the important part, don't die by the plan. &lt;strong&gt;Plans that are too tight have no room to absorb the inevitable&lt;/strong&gt;: a flu, a flaky test, a rabbit hole, that one dependency that decides to deprecate itself the week you need it. &lt;em&gt;If something can go wrong, it will go wrong&lt;/em&gt;. Plan for it.&lt;/p&gt;


&lt;div class="ltag__wikipedia--container"&gt;
  &lt;div class="ltag__wikipedia--header"&gt;
    &lt;img src="https://assets.dev.to/assets/wikipedia-logo-0a3e76624c7b1c3ccdeb9493ea4add6ef5bd82d7e88d102d5ddfd7c981efa2e7.svg" class="ltag__wikipedia--logo" alt="Wikipedia Logo" width="128" height="128"&gt;
    &lt;a href="https://en.wikipedia.org/wiki/Murphy%27s_law" rel="noopener noreferrer"&gt;Murphy's law&lt;/a&gt;
  &lt;/div&gt;
  &lt;div class="ltag__wikipedia--extract"&gt;&lt;p&gt;&lt;b&gt;Murphy's law&lt;/b&gt; is an adage or epigram that is typically stated as: "Anything that can go wrong &lt;i&gt;will&lt;/i&gt; go wrong."&lt;/p&gt;&lt;/div&gt;
  &lt;div class="ltag__wikipedia--btn--container"&gt;
      &lt;a class="ltag__wikipedia--btn" href="https://en.wikipedia.org/wiki/Murphy%27s_law" rel="noopener noreferrer"&gt;View on Wikipedia&lt;/a&gt;&amp;gt;
  &lt;/div&gt;
&lt;/div&gt;


&lt;h2&gt;
  
  
  When to use AI (and when to put your hands on the keyboard)
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Use AI to plan, not to know.
&lt;/h3&gt;

&lt;p&gt;AI is genuinely great for getting your bearings in a new codebase: "what does this module do", "where is X handled", "give me a tour of this folder". The trap is that it'll happily give you confident answers that feel like understanding without actually being understanding. Always review the plan it gives you. Always question its assumptions. &lt;strong&gt;At the end of the summer, nobody is evaluating the LLM. They're evaluating you&lt;/strong&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Don't let AI eat your learning.
&lt;/h3&gt;

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

&lt;p&gt;This is the part I want you to take most seriously. GSoC is one of the safest spaces you'll ever get to make mistakes: you have a mentor, a stipend, and explicit permission to be a beginner. If you outsource the thinking to an LLM, you're trading the most valuable thing about the program for some saved keystrokes. Especially when it comes to understanding issues: sit with the problem first. Read the code. Form your own theory. Then maybe ask the AI for a second opinion. &lt;strong&gt;AI already "knows" a lot of stuff. The whole point of the summer is: what do you know?&lt;/strong&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Balance check: we don't want you to feel we (or I) hate AI. AI is really cool and I'm very happy on using it. But as prof. Oak liked to say: "There's a place and time for everything". AI is cool, but the human using it is cooler.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  Maintainers can smell it.
&lt;/h3&gt;

&lt;p&gt;I've reviewed enough PRs to tell you this isn't a cute claim: it's true. Code that's 100% AI and 0% human reads differently. The variable names are too generic, the comments explain things nobody would explain, the solution is technically correct but doesn't fit the shape of the codebase, the PR title and/or the code make no sense. Mentors will spot it. And we, the mentors, want you to learn, that's the whole point of GSoC. We want more maintainers for the future. You can be one of them if you use this opportunity.&lt;/p&gt;

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

&lt;h2&gt;
  
  
  Wrapping up
&lt;/h2&gt;

&lt;p&gt;You'll quickly realize getting selected was the easiest part. &lt;strong&gt;This summer is the real thing&lt;/strong&gt;. Drive your own work, ask the smart questions, ship the small stuff, keep AI as a tool and not as a crutch and you'll come out the other side a much better engineer than the one who opened that email yesterday.&lt;/p&gt;

&lt;p&gt;See you at the final eval 👋&lt;/p&gt;

</description>
      <category>opensource</category>
      <category>gsoc</category>
      <category>software</category>
      <category>webdev</category>
    </item>
    <item>
      <title>Got featured :noice:</title>
      <dc:creator>Kevin Alemán</dc:creator>
      <pubDate>Tue, 10 Mar 2026 16:45:59 +0000</pubDate>
      <link>https://dev.to/kaleman15/-i0</link>
      <guid>https://dev.to/kaleman15/-i0</guid>
      <description>&lt;div class="ltag__link--embedded"&gt;
  &lt;div class="crayons-story "&gt;
  &lt;a href="https://dev.to/devteam/top-7-featured-dev-posts-of-the-week-1889" class="crayons-story__hidden-navigation-link"&gt;Top 7 Featured DEV Posts of the Week&lt;/a&gt;


  &lt;div class="crayons-story__body crayons-story__body-full_post"&gt;
    &lt;div class="crayons-story__top"&gt;
      &lt;div class="crayons-story__meta"&gt;
        &lt;div class="crayons-story__author-pic"&gt;
          &lt;a class="crayons-logo crayons-logo--l" href="/devteam"&gt;
            &lt;img alt="The DEV Team logo" src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Forganization%2Fprofile_image%2F1%2Fd908a186-5651-4a5a-9f76-15200bc6801f.jpg" class="crayons-logo__image" width="800" height="800"&gt;
          &lt;/a&gt;

          &lt;a href="/jess" class="crayons-avatar  crayons-avatar--s absolute -right-2 -bottom-2 border-solid border-2 border-base-inverted  "&gt;
            &lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F264%2Fb75f6edf-df7b-406e-a56b-43facafb352c.jpg" alt="jess profile" class="crayons-avatar__image" width="400" height="400"&gt;
          &lt;/a&gt;
        &lt;/div&gt;
        &lt;div&gt;
          &lt;div&gt;
            &lt;a href="/jess" class="crayons-story__secondary fw-medium m:hidden"&gt;
              Jess Lee
            &lt;/a&gt;
            &lt;div class="profile-preview-card relative mb-4 s:mb-0 fw-medium hidden m:inline-block"&gt;
              
                Jess Lee
                &lt;a href="/++"&gt;&lt;img alt="Subscriber" class="subscription-icon" src="https://assets.dev.to/assets/subscription-icon-805dfa7ac7dd660f07ed8d654877270825b07a92a03841aa99a1093bd00431b2.png" width="166" height="102"&gt;&lt;/a&gt;
                &lt;img alt="Community Curator" class="community-leader-icon" src="https://assets.dev.to/assets/community-leader-icon-b72c9e74eff54916e5c46c962f47ba40c9f611a71f8b157511f9613f69c0001b.svg" width="20" height="20"&gt;
              
              &lt;div id="story-author-preview-content-3331226" class="profile-preview-card__content crayons-dropdown branded-7 p-4 pt-0"&gt;
                &lt;div class="gap-4 grid"&gt;
                  &lt;div class="-mt-4"&gt;
                    &lt;a href="/jess" class="flex"&gt;
                      &lt;span class="crayons-avatar crayons-avatar--xl mr-2 shrink-0"&gt;
                        &lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F264%2Fb75f6edf-df7b-406e-a56b-43facafb352c.jpg" class="crayons-avatar__image" alt="" width="400" height="400"&gt;
                      &lt;/span&gt;
                      &lt;span class="crayons-link crayons-subtitle-2 mt-5"&gt;Jess Lee&lt;/span&gt;
                    &lt;/a&gt;
                  &lt;/div&gt;
                  &lt;div class="print-hidden"&gt;
                    
                      Follow
                    
                  &lt;/div&gt;
                  &lt;div class="author-preview-metadata-container"&gt;&lt;/div&gt;
                &lt;/div&gt;
              &lt;/div&gt;
            &lt;/div&gt;

            &lt;span&gt;
              &lt;span class="crayons-story__tertiary fw-normal"&gt; for &lt;/span&gt;&lt;a href="/devteam" class="crayons-story__secondary fw-medium"&gt;The DEV Team&lt;/a&gt;
            &lt;/span&gt;
          &lt;/div&gt;
          &lt;a href="https://dev.to/devteam/top-7-featured-dev-posts-of-the-week-1889" class="crayons-story__tertiary fs-xs"&gt;&lt;time&gt;Mar 10&lt;/time&gt;&lt;span class="time-ago-indicator-initial-placeholder"&gt;&lt;/span&gt;&lt;/a&gt;
        &lt;/div&gt;
      &lt;/div&gt;

    &lt;/div&gt;

    &lt;div class="crayons-story__indention"&gt;
      &lt;h2 class="crayons-story__title crayons-story__title-full_post"&gt;
        &lt;a href="https://dev.to/devteam/top-7-featured-dev-posts-of-the-week-1889" id="article-link-3331226"&gt;
          Top 7 Featured DEV Posts of the Week
        &lt;/a&gt;
      &lt;/h2&gt;
        &lt;div class="crayons-story__tags"&gt;
            &lt;a class="crayons-tag crayons-tag--filled  " href="/t/discuss"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;discuss&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/top7"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;top7&lt;/a&gt;
        &lt;/div&gt;
      &lt;div class="crayons-story__bottom"&gt;
        &lt;div class="crayons-story__details"&gt;
          &lt;a href="https://dev.to/devteam/top-7-featured-dev-posts-of-the-week-1889" class="crayons-btn crayons-btn--s crayons-btn--ghost crayons-btn--icon-left"&gt;
            &lt;div class="multiple_reactions_aggregate"&gt;
              &lt;span class="multiple_reactions_icons_container"&gt;
                  &lt;span class="crayons_icon_container"&gt;
                    &lt;img src="https://assets.dev.to/assets/multi-unicorn-b44d6f8c23cdd00964192bedc38af3e82463978aa611b4365bd33a0f1f4f3e97.svg" width="24" height="24"&gt;
                  &lt;/span&gt;
                  &lt;span class="crayons_icon_container"&gt;
                    &lt;img src="https://assets.dev.to/assets/fire-f60e7a582391810302117f987b22a8ef04a2fe0df7e3258a5f49332df1cec71e.svg" width="24" height="24"&gt;
                  &lt;/span&gt;
                  &lt;span class="crayons_icon_container"&gt;
                    &lt;img src="https://assets.dev.to/assets/sparkle-heart-5f9bee3767e18deb1bb725290cb151c25234768a0e9a2bd39370c382d02920cf.svg" width="24" height="24"&gt;
                  &lt;/span&gt;
              &lt;/span&gt;
              &lt;span class="aggregate_reactions_counter"&gt;47&lt;span class="hidden s:inline"&gt;&amp;nbsp;reactions&lt;/span&gt;&lt;/span&gt;
            &lt;/div&gt;
          &lt;/a&gt;
            &lt;a href="https://dev.to/devteam/top-7-featured-dev-posts-of-the-week-1889#comments" class="crayons-btn crayons-btn--s crayons-btn--ghost crayons-btn--icon-left flex items-center"&gt;
              

              18&lt;span class="hidden s:inline"&gt;&amp;nbsp;comments&lt;/span&gt;
            &lt;/a&gt;
        &lt;/div&gt;
        &lt;div class="crayons-story__save"&gt;
          &lt;small class="crayons-story__tertiary fs-xs mr-2"&gt;
            3 min read
          &lt;/small&gt;
        &lt;/div&gt;
      &lt;/div&gt;
    &lt;/div&gt;
  &lt;/div&gt;
&lt;/div&gt;

&lt;/div&gt;


</description>
      <category>top7</category>
      <category>discuss</category>
    </item>
    <item>
      <title>🙌🏽</title>
      <dc:creator>Kevin Alemán</dc:creator>
      <pubDate>Sun, 08 Mar 2026 18:51:54 +0000</pubDate>
      <link>https://dev.to/kaleman15/-j59</link>
      <guid>https://dev.to/kaleman15/-j59</guid>
      <description>&lt;div class="ltag__link--embedded"&gt;
  &lt;div class="crayons-story "&gt;
  &lt;a href="https://dev.to/kaleman15/in-the-ai-era-code-is-cheap-reputation-isnt-3482" class="crayons-story__hidden-navigation-link"&gt;In the AI Era, Code Is Cheap. Reputation Isn’t.&lt;/a&gt;


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

          &lt;a href="/kaleman15" class="crayons-avatar  crayons-avatar--l  "&gt;
            &lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F255126%2F6bdaeb84-6c1e-4e76-9d45-54c59eaac908.jpeg" alt="kaleman15 profile" class="crayons-avatar__image" width="460" height="460"&gt;
          &lt;/a&gt;
        &lt;/div&gt;
        &lt;div&gt;
          &lt;div&gt;
            &lt;a href="/kaleman15" class="crayons-story__secondary fw-medium m:hidden"&gt;
              Kevin Alemán
            &lt;/a&gt;
            &lt;div class="profile-preview-card relative mb-4 s:mb-0 fw-medium hidden m:inline-block"&gt;
              
                Kevin Alemán
                
                
              
              &lt;div id="story-author-preview-content-3309486" class="profile-preview-card__content crayons-dropdown branded-7 p-4 pt-0"&gt;
                &lt;div class="gap-4 grid"&gt;
                  &lt;div class="-mt-4"&gt;
                    &lt;a href="/kaleman15" class="flex"&gt;
                      &lt;span class="crayons-avatar crayons-avatar--xl mr-2 shrink-0"&gt;
                        &lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F255126%2F6bdaeb84-6c1e-4e76-9d45-54c59eaac908.jpeg" class="crayons-avatar__image" alt="" width="460" height="460"&gt;
                      &lt;/span&gt;
                      &lt;span class="crayons-link crayons-subtitle-2 mt-5"&gt;Kevin Alemán&lt;/span&gt;
                    &lt;/a&gt;
                  &lt;/div&gt;
                  &lt;div class="print-hidden"&gt;
                    
                      Follow
                    
                  &lt;/div&gt;
                  &lt;div class="author-preview-metadata-container"&gt;&lt;/div&gt;
                &lt;/div&gt;
              &lt;/div&gt;
            &lt;/div&gt;

          &lt;/div&gt;
          &lt;a href="https://dev.to/kaleman15/in-the-ai-era-code-is-cheap-reputation-isnt-3482" class="crayons-story__tertiary fs-xs"&gt;&lt;time&gt;Mar 4&lt;/time&gt;&lt;span class="time-ago-indicator-initial-placeholder"&gt;&lt;/span&gt;&lt;/a&gt;
        &lt;/div&gt;
      &lt;/div&gt;

    &lt;/div&gt;

    &lt;div class="crayons-story__indention"&gt;
      &lt;h2 class="crayons-story__title crayons-story__title-full_post"&gt;
        &lt;a href="https://dev.to/kaleman15/in-the-ai-era-code-is-cheap-reputation-isnt-3482" id="article-link-3309486"&gt;
          In the AI Era, Code Is Cheap. Reputation Isn’t.
        &lt;/a&gt;
      &lt;/h2&gt;
        &lt;div class="crayons-story__tags"&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/ai"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;ai&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/opensource"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;opensource&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/programming"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;programming&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/software"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;software&lt;/a&gt;
        &lt;/div&gt;
      &lt;div class="crayons-story__bottom"&gt;
        &lt;div class="crayons-story__details"&gt;
          &lt;a href="https://dev.to/kaleman15/in-the-ai-era-code-is-cheap-reputation-isnt-3482" class="crayons-btn crayons-btn--s crayons-btn--ghost crayons-btn--icon-left"&gt;
            &lt;div class="multiple_reactions_aggregate"&gt;
              &lt;span class="multiple_reactions_icons_container"&gt;
                  &lt;span class="crayons_icon_container"&gt;
                    &lt;img src="https://assets.dev.to/assets/exploding-head-daceb38d627e6ae9b730f36a1e390fca556a4289d5a41abb2c35068ad3e2c4b5.svg" width="24" height="24"&gt;
                  &lt;/span&gt;
                  &lt;span class="crayons_icon_container"&gt;
                    &lt;img src="https://assets.dev.to/assets/raised-hands-74b2099fd66a39f2d7eed9305ee0f4553df0eb7b4f11b01b6b1b499973048fe5.svg" width="24" height="24"&gt;
                  &lt;/span&gt;
                  &lt;span class="crayons_icon_container"&gt;
                    &lt;img src="https://assets.dev.to/assets/sparkle-heart-5f9bee3767e18deb1bb725290cb151c25234768a0e9a2bd39370c382d02920cf.svg" width="24" height="24"&gt;
                  &lt;/span&gt;
              &lt;/span&gt;
              &lt;span class="aggregate_reactions_counter"&gt;31&lt;span class="hidden s:inline"&gt;&amp;nbsp;reactions&lt;/span&gt;&lt;/span&gt;
            &lt;/div&gt;
          &lt;/a&gt;
            &lt;a href="https://dev.to/kaleman15/in-the-ai-era-code-is-cheap-reputation-isnt-3482#comments" class="crayons-btn crayons-btn--s crayons-btn--ghost crayons-btn--icon-left flex items-center"&gt;
              

              17&lt;span class="hidden s:inline"&gt;&amp;nbsp;comments&lt;/span&gt;
            &lt;/a&gt;
        &lt;/div&gt;
        &lt;div class="crayons-story__save"&gt;
          &lt;small class="crayons-story__tertiary fs-xs mr-2"&gt;
            6 min read
          &lt;/small&gt;
        &lt;/div&gt;
      &lt;/div&gt;
    &lt;/div&gt;
  &lt;/div&gt;
&lt;/div&gt;

&lt;/div&gt;


</description>
      <category>ai</category>
      <category>opensource</category>
      <category>programming</category>
      <category>software</category>
    </item>
    <item>
      <title>In the AI Era, Code Is Cheap. Reputation Isn’t.</title>
      <dc:creator>Kevin Alemán</dc:creator>
      <pubDate>Wed, 04 Mar 2026 21:01:29 +0000</pubDate>
      <link>https://dev.to/kaleman15/in-the-ai-era-code-is-cheap-reputation-isnt-3482</link>
      <guid>https://dev.to/kaleman15/in-the-ai-era-code-is-cheap-reputation-isnt-3482</guid>
      <description>&lt;p&gt;In the era of AI it's easier than ever to be an Open Source contributor!&lt;/p&gt;

&lt;p&gt;But, at the same time, and quite paradoxically, it's harder than ever.&lt;/p&gt;

&lt;p&gt;Why? Because it's now &lt;em&gt;mechanically easier, but reputationally harder&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Previously, you competed against other incredibly smart volunteers, or maybe against employed developers that contributed their expertise and free time to open source, or against newcomers. Now, you compete against all of that and an army of AI agents generating pull requests, issues, refactors and vulnerability reports faster than what any human can do.&lt;/p&gt;

&lt;p&gt;It's pretty tempting. Using an LLM can reduce significantly the cognitive work you have to do to understand a codebase, and even to produce a valuable change request. Things that were previously "very hard" to do are now a few prompts away, and that lowered the entry barrier for contributions, which is great! But also created a massive increase in volume, which is flooding repositories.&lt;/p&gt;

&lt;p&gt;What's the problem? &lt;br&gt;
&lt;em&gt;Maintainer capacity did not increase&lt;/em&gt;&lt;br&gt;
&lt;em&gt;Review cost did not decrease&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;These two truths have already led maintainer to resort to drastic measures, like what happened with &lt;code&gt;curl&lt;/code&gt;:&lt;/p&gt;


&lt;div class="crayons-card c-embed text-styles text-styles--secondary"&gt;
    &lt;div class="c-embed__content"&gt;
        &lt;div class="c-embed__cover"&gt;
          &lt;a href="https://daniel.haxx.se/blog/2025/07/14/death-by-a-thousand-slops/" class="c-link align-middle" rel="noopener noreferrer"&gt;
            &lt;img alt="" src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdaniel.haxx.se%2Fblog%2Fwp-content%2Fuploads%2F2017%2F09%2Fbug-insect-1200x803.jpg" height="535" class="m-0" width="800"&gt;
          &lt;/a&gt;
        &lt;/div&gt;
      &lt;div class="c-embed__body"&gt;
        &lt;h2 class="fs-xl lh-tight"&gt;
          &lt;a href="https://daniel.haxx.se/blog/2025/07/14/death-by-a-thousand-slops/" rel="noopener noreferrer" class="c-link"&gt;
            Death by a thousand slops | daniel.haxx.se
          &lt;/a&gt;
        &lt;/h2&gt;
        &lt;div class="color-secondary fs-s flex items-center"&gt;
            &lt;img alt="favicon" class="c-embed__favicon m-0 mr-2 radius-0" src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdaniel.haxx.se%2Fblog%2Fwp-content%2Fuploads%2F2024%2F07%2Fdaniel-greenbg-blackandwhite-413x413-1.jpg" width="413" height="413"&gt;
          daniel.haxx.se
        &lt;/div&gt;
      &lt;/div&gt;
    &lt;/div&gt;
&lt;/div&gt;


&lt;p&gt;So, how do you become a valuable Open Source contributor in the era of infinite code generation? Here are a few tips learned from dealing with a large volume of contributions:&lt;/p&gt;

&lt;h2&gt;
  
  
  1. Think. Then think again
&lt;/h2&gt;

&lt;p&gt;AI can produce great code, but it can also produce the worst code ever seen by the humanity. This depends a lot on:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The &lt;em&gt;prompt&lt;/em&gt; that you use&lt;/li&gt;
&lt;li&gt;The &lt;em&gt;quality&lt;/em&gt; of the LLM&lt;/li&gt;
&lt;li&gt;The &lt;em&gt;context&lt;/em&gt; being shared&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;And the most important one:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Your own coding abilities.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Why do you need to know how to code before using LLMs to contribute to open source?&lt;/p&gt;

&lt;p&gt;Well, &lt;em&gt;because an LLM cannot know everything.&lt;/em&gt;&lt;br&gt;
For example, we had a PR that attempted to change this:&lt;/p&gt;

&lt;p&gt;Previous:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;        &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;catch &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Some error:&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;After&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;        &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;catch &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="nx"&gt;logger&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Some error:&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;You would say: that is a valid change, we want to use &lt;code&gt;logger&lt;/code&gt; instead of &lt;code&gt;console&lt;/code&gt;! What's the problem?&lt;/p&gt;

&lt;p&gt;The problem was that the LLM didn't know (and didn't check, cause it wasn't asked to) that we recently changed the typings on our &lt;code&gt;logger&lt;/code&gt; instances, rendering the change invalid.&lt;/p&gt;

&lt;p&gt;What a valid change would have looked like:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;        &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;catch &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="nx"&gt;logger&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;error&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;msg&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Some error&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;err&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;But, the LLM didn't know this, and it would have required quite some context for it to know. Good LLMs (Claude, Codex, etc) would have caught, but others would not, unless you asked them. How would you ask something that you didn't know? There's where your coding abilities enter into play.&lt;/p&gt;

&lt;p&gt;Here's the key point: &lt;em&gt;You cannot prompt what you don't know exists&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Someone that wants to be a contributor doesn't trust blindly on what the LLM produces. Knows how to use the tooling (typecheck, in this case) to catch those issues, reads the code to understand current conventions, caveats, etc.&lt;br&gt;
For this programmers, &lt;em&gt;LLMs become a powerful tool&lt;/em&gt;, cause it helps you with the mechanical task of coding and gives you enough time to think.&lt;/p&gt;

&lt;p&gt;This also protects your reputation. If maintainers see a pattern of low-signal PRs from you, they’ll eventually stop reviewing them. Or worse.&lt;/p&gt;

&lt;p&gt;LLMs make contribution faster, but they don’t replace your brain unless you let them.&lt;/p&gt;
&lt;h2&gt;
  
  
  2. Respect volume. Review is not free.
&lt;/h2&gt;

&lt;p&gt;You are happy. We're also happy that you want to contribute to open source. It's a noble endeavor and it's something that helps the repository to be safer &amp;amp; you to be better. It's a win-win!&lt;/p&gt;

&lt;p&gt;But, maintainers have:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Limited capacity. &lt;/li&gt;
&lt;li&gt;Limited time. &lt;/li&gt;
&lt;li&gt;&lt;em&gt;Limited patience.&lt;/em&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;We understand, you are happy you created your new PR, and we understand the joy in you of doing that. We've all being there. You want, for sure, your PR to be merged so you can say with honor: "I contributed to X!"&lt;/p&gt;

&lt;p&gt;But, be reasonable:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The cost of opening a PR is now near zero.&lt;/li&gt;
&lt;li&gt;The cost of &lt;em&gt;reviewing&lt;/em&gt; it is not.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This asymmetry is the real tension of the AI era.&lt;/p&gt;

&lt;p&gt;If you:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;comment “please review” repeatedly,&lt;/li&gt;
&lt;li&gt;ping maintainers aggressively,&lt;/li&gt;
&lt;li&gt;demand merging timelines,&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;You’re increasing the cognitive cost of your contribution. Even if your PR is valid.&lt;/p&gt;

&lt;p&gt;And here’s the harsh truth:&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Maintainers are human.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;If interacting with you feels expensive, they may subconsciously deprioritize your work. That means fewer reviews, fewer merges, fewer release notes mentions.&lt;/p&gt;

&lt;p&gt;This is specially important when you use LLMs or Agents as they are fast, way faster than humans, so you could end up doing 100 PRs that you think are valid, and maybe they are! But if the maintainers don't have the capacity to review them all, they just won't.&lt;/p&gt;

&lt;p&gt;That's the definition of a DoS (Denial of Service): you send more requests than what the server (maintainers) can process.&lt;/p&gt;
&lt;h2&gt;
  
  
  3. Quality that doesn't cut corners (pls don't sue me Wendy's)
&lt;/h2&gt;

&lt;p&gt;Maintainer capacity is low. We closed around 700 issues (stale, invalid, fixed) in the past month, but at the same time, we received 300 new issues. Some of those issues were valid, some of them were not. The problem is we don't know beforehand, &lt;em&gt;we have to check them all&lt;/em&gt;. You cannot trust an LLM to confirm if something is slop... cause the check may be slop too!&lt;/p&gt;

&lt;p&gt;Related link, &lt;code&gt;curl&lt;/code&gt; fighting against AI slop vulnerability reports:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://hackerone.com/reports/3516186" rel="noopener noreferrer"&gt;HackerOne Curl report&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;As you see, maintainers won't be happy if you waste their time, cause they have stuff to do. The link above, as well as this beautiful list&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;



&lt;p&gt;have something in common: they look legit, until they don't. However, for realising something is slop you have to check manually, and that is time/effort wasted.&lt;/p&gt;

&lt;p&gt;So you have to be human, respect the times maintainers have and respect their work. How you do that? &lt;em&gt;Helping the maintainers reduce the cost of reviewing your code&lt;/em&gt;:&lt;/p&gt;

&lt;p&gt;Before submitting:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Did you reproduce the issue yourself?&lt;/li&gt;
&lt;li&gt;Did you run CI locally?&lt;/li&gt;
&lt;li&gt;Did you include screenshots for UI changes?&lt;/li&gt;
&lt;li&gt;Did you provide benchmarks for performance claims?&lt;/li&gt;
&lt;li&gt;Did you include a PoC for security reports?&lt;/li&gt;
&lt;li&gt;Did you check if a feature request already exists?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If you claim a performance improvement, &lt;em&gt;show numbers&lt;/em&gt;.&lt;br&gt;
If you fix a bug, &lt;em&gt;explain the root cause&lt;/em&gt;.&lt;br&gt;
If you propose a feature, &lt;em&gt;ask first&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;High quality contributions get reviewed faster.&lt;br&gt;
Low signal contributions accumulate.&lt;/p&gt;

&lt;p&gt;In the AI era, &lt;em&gt;reputation compounds&lt;/em&gt;. If maintainers can trust you, your PRs will be reviewed faster, and you will feel happier. Win-win!&lt;/p&gt;
&lt;h2&gt;
  
  
  4. Bundle trivial changes.
&lt;/h2&gt;

&lt;p&gt;Typos happen. Smol mistakes happen. For example &lt;/p&gt;

&lt;p&gt;Before:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;        &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;sub&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&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="nc"&gt;Error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;subsciption not found&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;After&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;        &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;sub&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&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="nc"&gt;Error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;subscription not found&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Do you spot the bug? Yep, a missing &lt;code&gt;r&lt;/code&gt; on &lt;code&gt;subscription&lt;/code&gt;. The contribution is valid, yes, we want to write correct words in english.&lt;/p&gt;

&lt;p&gt;Does it deserve a PR? Not by itself, maybe if you combine a few more. Think if you find 10 of those misspellings. What's easier for maintainers? 1 PR with 10 changes or 10 PRs with 1 change? Hehe.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;If you were the maintainer, what would you prefer?&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Every PR has overhead: CI runs, notifications, review time, merge time, mental context switch, etc. Reduce the overhead by batching trivial work.&lt;/p&gt;

&lt;p&gt;AI can find an enormous list of fixes like this in a codebase, and if you use an agent like Claude or Clawd you can tell "Hey for each issue create a PR" and then become the most hated contributor on the project :(&lt;/p&gt;

&lt;p&gt;Don't do that. Please. Be mindful. &lt;em&gt;Be human&lt;/em&gt;.&lt;/p&gt;
&lt;h2&gt;
  
  
  LLMs are fun, but human work is better.
&lt;/h2&gt;

&lt;p&gt;We're on the AI era, we cannot fight AIs anymore, they're here to stay. What we can fight is how we use them.&lt;/p&gt;

&lt;p&gt;For GSoC for example, we value human contributions. That's the point of the program: more humans converting to open source contributors!&lt;/p&gt;

&lt;p&gt;We need new generations of maintainers, of smart people that will use LLMs wisely. You can do amazing stuff with them if you use them properly, but nothing will replace your ability to do amazing stuff as a human. You have to remember that.&lt;/p&gt;

&lt;p&gt;It's easier to contribute, but harder to stand out from the crowd.&lt;br&gt;
Reputation matters.&lt;br&gt;
Trust is earned.&lt;br&gt;
You build it by doing good work.&lt;/p&gt;

&lt;p&gt;As a final note, this is pretty much personal experience. Some projects may have different rules. Some may like to receive 1000 PRs a day (?) idk.&lt;/p&gt;

&lt;p&gt;But, the main point is: AI is not human, but maintainers and contributors are. So remember that.&lt;/p&gt;

&lt;p&gt;Welcome to Open Source!&lt;/p&gt;

&lt;p&gt;If u want to read more:&lt;br&gt;
&lt;/p&gt;
&lt;div class="crayons-card c-embed text-styles text-styles--secondary"&gt;
    &lt;div class="c-embed__content"&gt;
      &lt;div class="c-embed__body"&gt;
        &lt;h2 class="fs-xl lh-tight"&gt;
          &lt;a href="https://www.jeffgeerling.com/blog/2026/ai-is-destroying-open-source/" rel="noopener noreferrer" class="c-link"&gt;
            AI is destroying Open Source, and it's not even good yet - Jeff Geerling
          &lt;/a&gt;
        &lt;/h2&gt;
          &lt;p class="truncate-at-3"&gt;
            Over the weekend Ars Technica retracted an article because the AI a writer used hallucinated quotes from an open source library maintainer.
The irony here is the maintainer in question, Scott Shambaugh, was harassed by someone's AI agent over not merging its AI slop code.
It's likely the bot was running through someone's local 'agentic AI' instance (likely using OpenClaw). The guy who built OpenClaw was just hired by OpenAI to "work on bringing agents to everyone." You'll have to forgive me if I'm not enthusastic about that.
          &lt;/p&gt;
        &lt;div class="color-secondary fs-s flex items-center"&gt;
          jeffgeerling.com
        &lt;/div&gt;
      &lt;/div&gt;
    &lt;/div&gt;
&lt;/div&gt;



</description>
      <category>ai</category>
      <category>opensource</category>
      <category>programming</category>
      <category>software</category>
    </item>
    <item>
      <title>You're doing great, and you need to hear that :)</title>
      <dc:creator>Kevin Alemán</dc:creator>
      <pubDate>Wed, 15 Sep 2021 16:09:03 +0000</pubDate>
      <link>https://dev.to/kaleman15/you-re-doing-great-and-you-need-to-hear-that-12ba</link>
      <guid>https://dev.to/kaleman15/you-re-doing-great-and-you-need-to-hear-that-12ba</guid>
      <description>&lt;p&gt;I'm not the kind of person that likes to be "thanked" for something. I like to do the things, and that's it. And later I realized it was not only me who felt this way. But, is receiving recognition something reserved for super special situations?&lt;/p&gt;

&lt;h2&gt;
  
  
  Everyone needs to be "praised" for doing a great work
&lt;/h2&gt;

&lt;p&gt;Being praised releases dopamine, that's why you feel happy when someone recognizes your work and says that it's good. Everyone likes that feeling of "doing something amazing" by receiving a simple "thanks for helping me". But, it doesn't stop there.&lt;/p&gt;

&lt;p&gt;Your motivation is also increased. It's important to note that everyone has a different set of motivators, so what may work for someone probably won't have the same effect for others. But there are some common motivators in a workplace, like the compensation. Receiving a considerable wage and a good compensation plan on your company may motivate you to work better. Same as having a clean workstation, or having a good team composed of capable people. Recognition is also a &lt;a href="https://www.thesuccessfactory.co.uk/blog/motivators-in-the-workplace-that-improve-employee-experience" rel="noopener noreferrer"&gt;key motivator&lt;/a&gt;, that means, surprisingly, that &lt;a href="https://www.trainingjournal.com/articles/feature/power-praise-and-recognition" rel="noopener noreferrer"&gt;people feel good&lt;/a&gt; when they're recognized :)&lt;/p&gt;

&lt;p&gt;However, as any other dopamine-releaser, the effect of recognition is transient, and, it may decrese the effect over time when it's done &lt;em&gt;too much&lt;/em&gt;. So, recognition should be given timely.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fk423mpsup0nb13ycv8l8.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fk423mpsup0nb13ycv8l8.gif" alt="Syndrome's line" width="480" height="270"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Timely recognition
&lt;/h2&gt;

&lt;p&gt;So, how do we achieve a recognition scheme that's not sporadic but is not rare at the same time? Balance, as always, is the key.&lt;/p&gt;

&lt;p&gt;This is more an HR topic, probably at your company there's a lot of people trying to fix this same issue, because recognition is not as easy as it may look. Fairness plays a &lt;em&gt;really&lt;/em&gt; important role. What if another employee who does the same thing I do receives recognition every week, but I receive it every year? Then, recognition becomes a problem and a demotivator, so it's important to watch out how recognition will be conducted.&lt;/p&gt;

&lt;p&gt;But, let's return to the frequency. From this &lt;a href="https://www.businessinsider.com/how-often-do-employees-need-recognition-2012-8" rel="noopener noreferrer"&gt;BI Article&lt;/a&gt;, a weekly recognition scheme is good. Probably you don't need it to be too frequent. Think for example, on sprints. If your sprints are 2 weeks long, why not dedicating some time at the end to thank your colleagues for their work?&lt;/p&gt;

&lt;p&gt;The same article says that this type of recognition helps the employee to be engaged, and trying to get that recognition again, because people like that. Try to avoid recognizing your employees just with the normal performance review cycle, because that may be too late.&lt;/p&gt;

&lt;p&gt;Again, if your colleague did something &lt;em&gt;really&lt;/em&gt; good for you or the team, don't wait to say thanks. Recognition has a "shelf life", that means, it can expire if not used at the right moment!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/https%3A%2F%2Fthumbs.gfycat.com%2FEnchantingSafeArizonaalligatorlizard-max-1mb.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/https%3A%2F%2Fthumbs.gfycat.com%2FEnchantingSafeArizonaalligatorlizard-max-1mb.gif" alt="Apu getting expired item from the shelves" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;So, key points for timely recognition:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Do it before it expires :)&lt;/li&gt;
&lt;li&gt;Don't wait to normal performance review cycles to recognize people&lt;/li&gt;
&lt;li&gt;Be fair&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  How to create a recognition culture?
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Make it easy&lt;br&gt;
Your team should feel that it's easy to give recognition. If people find a lot of requirements or an extremely formal process for doing so, they won't do it.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Be specific&lt;br&gt;
Saying "thanks" is good, but it's even better when you know &lt;em&gt;the reason&lt;/em&gt; for that. So saying "thanks for helping me with the last presentation" would be much more valuable than just saying thanks, because that means you're recognizing &lt;em&gt;a specific effort&lt;/em&gt;, and not just saying a canned response.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Connect the dots :)&lt;br&gt;
Relate the recognition with your company's values. This makes easier for your team to know how they're contributing to the company's objectives and culture, and that creates a strong culture :)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Make it for everyone&lt;br&gt;
Avoid having only managers giving recognition. Foster p2p recognition, since that'll create bounds between your team.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;(Key points taken from &lt;a href="https://www.greatgame.com/blog/creating-a-recognition-culture-best-practices" rel="noopener noreferrer"&gt;this article&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;So, as conclusion, thanks for what you're doing to improve the community :) and thanks for sharing your knowledge with the rest of the people using this platform.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Furw26vjcobmnds2984jb.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Furw26vjcobmnds2984jb.jpg" alt="Simpsons' Monstromart: we love you" width="720" height="576"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now, go there and recognize people for what they're doing :)&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>mentalhealth</category>
      <category>beginners</category>
    </item>
  </channel>
</rss>
