<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"><channel><title>mainLog: The unwritten rules</title><description>Habits most codebases rely on without ever stating them. I write each one down and test it against real code and data, to see whether it deserves to stay.</description><link>https://mainlog.dev/</link><language>en</language><item><title>When to merge duplicate code</title><link>https://mainlog.dev/posts/when-to-merge-duplicate-code/</link><guid isPermaLink="true">https://mainlog.dev/posts/when-to-merge-duplicate-code/</guid><description>Whether two similar functions should become one depends on whether they change together, and git already knows. A real history from httpx, a script that counts co-changes across a repository, a browser tool for one pair, and a third answer that is neither copying nor abstracting: generate one copy and check it.</description><pubDate>Mon, 17 Aug 2026 00:00:00 GMT</pubDate></item><item><title>Every latency number answers one question</title><link>https://mainlog.dev/posts/measuring-latency/</link><guid isPermaLink="true">https://mainlog.dev/posts/measuring-latency/</guid><description>A checkout page hangs while the dashboard says 23 ms. The mean, a percentile and a share under a threshold each answer a different question, only two of them add up across hosts, and an averaged p99 can be wrong by a factor of three in either direction.</description><pubDate>Tue, 25 Aug 2026 00:00:00 GMT</pubDate></item><item><title>Code review economics</title><link>https://mainlog.dev/posts/code-review-economics/</link><guid isPermaLink="true">https://mainlog.dev/posts/code-review-economics/</guid><description>On three busy repositories the wait for a first review grows much more slowly than a PR&apos;s size, so a change split into eight PRs reviewed one after another waits three to eight times as long. Opening them side by side helps less than it looks, and only one reviewer taking them together is no worse than one PR. The measurement, the rule that falls out of it, and a tool to run it on your own PRs.</description><pubDate>Tue, 13 Oct 2026 00:00:00 GMT</pubDate></item><item><title>Keeping optional Python imports optional</title><link>https://mainlog.dev/posts/optional-python-imports/</link><guid isPermaLink="true">https://mainlog.dev/posts/optional-python-imports/</guid><description>A test that checks importing a library leaves its optional dependency unloaded, and proves it got far enough to notice.</description><pubDate>Mon, 31 Aug 2026 00:00:00 GMT</pubDate></item><item><title>Green on my laptop, red in CI</title><link>https://mainlog.dev/posts/pytest-plugin-ci-only-failures/</link><guid isPermaLink="true">https://mainlog.dev/posts/pytest-plugin-ci-only-failures/</guid><description>A pytest plugin passed every test from the source checkout and failed twice in CI, because only the installed wheel told pytest the plugin existed.</description><pubDate>Tue, 15 Sep 2026 00:00:00 GMT</pubDate></item><item><title>How many concepts is too many</title><link>https://mainlog.dev/posts/concept-count/</link><guid isPermaLink="true">https://mainlog.dev/posts/concept-count/</guid><description>Framework debates trade concept counts that measure different things. Count what the smallest real program makes its user write, in separate columns and per reader, find the rules the count can&apos;t see by misspelling them, and keep an extra concept only when it moves a check earlier or gives users a seam they can see.</description><pubDate>Fri, 02 Oct 2026 00:00:00 GMT</pubDate></item><item><title>The one-sentence API design test</title><link>https://mainlog.dev/posts/one-sentence-api/</link><guid isPermaLink="true">https://mainlog.dev/posts/one-sentence-api/</guid><description>Six AI agents each designed one extension to my framework, and each design held up on its own. Side by side they disagreed about names every user touches. One question sorted them out, and writing down the rules my existing code already followed made the answer countable.</description><pubDate>Wed, 21 Oct 2026 00:00:00 GMT</pubDate></item><item><title>What plugin discovery actually checks</title><link>https://mainlog.dev/posts/plugin-discovery/</link><guid isPermaLink="true">https://mainlog.dev/posts/plugin-discovery/</guid><description>A plugin you can see in pip list comes back “not found”. Python hosts turn installed entry points into loaded code in four checks, and the order of those checks decides whether a plugin&apos;s code runs before anyone asks if it fits, and whether the error your code catches says why.</description><pubDate>Fri, 04 Sep 2026 00:00:00 GMT</pubDate></item></channel></rss>