<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Home on Alexey Panfilov — Product, AI, Systems</title><link>https://dzarlax.dev/</link><description>Recent content in Home on Alexey Panfilov — Product, AI, Systems</description><generator>Hugo</generator><language>en</language><atom:link href="https://dzarlax.dev/index.xml" rel="self" type="application/rss+xml"/><item><title>I Tried to Automate Blog Translation. The Real Product Was QA.</title><link>https://dzarlax.dev/articles/i-tried-to-automate-blog-translation.-the-real-product-was-qa./</link><pubDate>Sat, 23 May 2026 00:00:00 +0000</pubDate><guid>https://dzarlax.dev/articles/i-tried-to-automate-blog-translation.-the-real-product-was-qa./</guid><description>&lt;p&gt;I started with a simple wish: I had English articles on dzarlax.dev, and I wanted Russian and Serbian versions without turning every post into a weekend project.&lt;/p&gt;
&lt;p&gt;The shape looked automatable. The source was already Markdown. The site already had language-aware routing. I write in an Obsidian vault. Article bundles are predictable:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;articles/&amp;lt;slug&amp;gt;/index.md
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;articles/&amp;lt;slug&amp;gt;/index.ru.md
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;articles/&amp;lt;slug&amp;gt;/index.rs.md
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;So the initial question sounded technical: which translation model should I use?&lt;/p&gt;
&lt;p&gt;That turned out to be the wrong question. The real question was: &lt;strong&gt;which parts of translation should be automated, and which parts should stay editorial?&lt;/strong&gt;&lt;/p&gt;</description></item><item><title>Health Dashboard, Part 1: A Score I Could Trust</title><link>https://dzarlax.dev/articles/health-dashboard-part-1-a-score-i-could-trust/</link><pubDate>Mon, 18 May 2026 00:00:00 +0000</pubDate><guid>https://dzarlax.dev/articles/health-dashboard-part-1-a-score-i-could-trust/</guid><description>&lt;p&gt;This is Part 1 of a series about building my self-hosted Health Dashboard. The first version was not a methodology project. It was a pipe: take data from Apple Health, POST it to my server, show a score in the morning.&lt;/p&gt;
&lt;p&gt;That sounds clean until the first bad night of data lands in Postgres. A health score is only as trustworthy as the ingestion path underneath it, and the early version of this system was mostly teaching me that lesson the hard way.&lt;/p&gt;</description></item><item><title>Health Dashboard, Part 2: Outgrowing Health Auto Export</title><link>https://dzarlax.dev/articles/health-dashboard-part-2-outgrowing-health-auto-export/</link><pubDate>Mon, 18 May 2026 00:00:00 +0000</pubDate><guid>https://dzarlax.dev/articles/health-dashboard-part-2-outgrowing-health-auto-export/</guid><description>&lt;p&gt;In Part 1 the server learned to accept observations without losing them and to rebuild every derived table from raw data. That was enough to make a dashboard useful. It was not enough to make the data honest.&lt;/p&gt;
&lt;p&gt;This part is about the moment a third-party exporter stopped being a sufficient ingestion path on its own, and about the two regressions that followed when I added my own iOS client alongside it. Health Auto Export still runs against the server today. The &lt;code&gt;/health&lt;/code&gt; endpoint accepts both producers, and the code path that parses HAE payloads is maintained. The &amp;ldquo;outgrowing&amp;rdquo; in the title is about its limits, not its retirement.&lt;/p&gt;</description></item><item><title>Health Dashboard, Part 3: My Wearables Kept Lying by Omission</title><link>https://dzarlax.dev/articles/health-dashboard-part-3-my-wearables-kept-lying-by-omission/</link><pubDate>Mon, 18 May 2026 00:00:00 +0000</pubDate><guid>https://dzarlax.dev/articles/health-dashboard-part-3-my-wearables-kept-lying-by-omission/</guid><description>&lt;p&gt;After Part 2 the ingestion layer feels clean. The server accepts payloads, a native iOS client cooperates with Health Auto Export, the schema knows about per-segment sleep, the dashboard renders five sleep phases. It looks finished. It is not.&lt;/p&gt;
&lt;p&gt;The next class of problem only became visible once the data was technically correct. On any given night I have &lt;strong&gt;three devices&lt;/strong&gt; capable of saying something about my sleep: Apple Watch on my wrist, RingConn&lt;sup id="fnref:1"&gt;&lt;a href="#fn:1" class="footnote-ref" role="doc-noteref"&gt;1&lt;/a&gt;&lt;/sup&gt; on my finger, and the iPhone next to my bed running Apple&amp;rsquo;s own Sleep Schedule estimate. Each one knows something the others do not. None of them agree about what they measured.&lt;/p&gt;</description></item><item><title>Health Dashboard, Part 4: When Readiness Stopped Being One Number</title><link>https://dzarlax.dev/articles/health-dashboard-part-4-when-readiness-stopped-being-one-number/</link><pubDate>Mon, 18 May 2026 00:00:00 +0000</pubDate><guid>https://dzarlax.dev/articles/health-dashboard-part-4-when-readiness-stopped-being-one-number/</guid><description>&lt;p&gt;In Part 1 I described the original readiness score:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;readiness = HRV_score * 0.40 + RHR_score * 0.30 + Sleep_score * 0.30
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;It was a useful number. It told me, every morning, whether something in last night&amp;rsquo;s data looked unusual against my personal baseline. It also turned out to be measuring the wrong thing.&lt;/p&gt;
&lt;p&gt;This part is the audit that surfaced that, the redesign that came out of it, and the moment Phase 1 closed without producing a single model that beat its naive baseline by the criterion we had set in advance.&lt;/p&gt;</description></item><item><title>Health Dashboard, Part 5: The Energy Bank Problem</title><link>https://dzarlax.dev/articles/health-dashboard-part-5-the-energy-bank-problem/</link><pubDate>Mon, 18 May 2026 00:00:00 +0000</pubDate><guid>https://dzarlax.dev/articles/health-dashboard-part-5-the-energy-bank-problem/</guid><description>&lt;p&gt;In Part 4 the audit invalidated the readiness formula and surfaced a parallel finding: EnergyBank v1 was wrong-signed against next-day HRV&lt;sup id="fnref:1"&gt;&lt;a href="#fn:1" class="footnote-ref" role="doc-noteref"&gt;1&lt;/a&gt;&lt;/sup&gt; (r=−0.149) and next-day RHR&lt;sup id="fnref:2"&gt;&lt;a href="#fn:2" class="footnote-ref" role="doc-noteref"&gt;2&lt;/a&gt;&lt;/sup&gt; (r=+0.212) over 387 paired days.&lt;/p&gt;
&lt;p&gt;Wrong-signed is a strong claim. It means the concept is intact but the target is mis-specified: what v1 was measuring was probably &lt;em&gt;productive strain&lt;/em&gt;, not &lt;em&gt;recovery deficit&lt;/em&gt;. The two correlate on many days and diverge precisely on the days that matter, like a quiet but anxious day, an illness, a watch off the wrist.&lt;/p&gt;</description></item><item><title>Health Dashboard, Part 6: Measuring Stress Without Lying to Myself</title><link>https://dzarlax.dev/articles/health-dashboard-part-6-measuring-stress-without-lying-to-myself/</link><pubDate>Mon, 18 May 2026 00:00:00 +0000</pubDate><guid>https://dzarlax.dev/articles/health-dashboard-part-6-measuring-stress-without-lying-to-myself/</guid><description>&lt;p&gt;In Part 5 the EnergyBank redesign left a placeholder: &lt;code&gt;drain = α · active_kcal + β · sustained_hr_load&lt;/code&gt;, with &lt;code&gt;β = 0&lt;/code&gt; until a validation rubric per-user returns &lt;code&gt;validated&lt;/code&gt;. That term, the autonomic-load drain, is the v2.2 piece. It is also the one I most wanted to be careful with, because &amp;ldquo;stress&amp;rdquo; is the single most over-claimed metric in consumer health products.&lt;/p&gt;
&lt;p&gt;This part is about what stress actually means physiologically, what my data can and cannot say about it, why the obvious formula was wrong, and what the rubric is for.&lt;/p&gt;</description></item><item><title>Health Dashboard, Part 7: The App That Stopped Doing the Math</title><link>https://dzarlax.dev/articles/health-dashboard-part-7-the-app-that-stopped-doing-the-math/</link><pubDate>Mon, 18 May 2026 00:00:00 +0000</pubDate><guid>https://dzarlax.dev/articles/health-dashboard-part-7-the-app-that-stopped-doing-the-math/</guid><description>&lt;p&gt;The first six parts of this series were about the server learning to have opinions. Ingestion gates, source identity, sub-score eligibility, formula-version boundaries, validation rubrics: every piece earned its right to a number. Once that work was done, a new question opened on the other side of the wire. What is the iOS client allowed to do with those numbers?&lt;/p&gt;
&lt;p&gt;The answer turned out to be narrower than I expected when I started. The interesting part of building the mobile app was not what got added to it. It was what got &lt;em&gt;removed&lt;/em&gt; from it, repeatedly, as the server learned to do each thing better.&lt;/p&gt;</description></item><item><title>Health Dashboard, Part 8: Asking Before Telling</title><link>https://dzarlax.dev/articles/health-dashboard-part-8-asking-before-telling/</link><pubDate>Mon, 18 May 2026 00:00:00 +0000</pubDate><guid>https://dzarlax.dev/articles/health-dashboard-part-8-asking-before-telling/</guid><description>&lt;p&gt;Part 6 said: subjective input cannot validate the stress formula. That rule stands. A formula that auto-tunes itself against a user&amp;rsquo;s self-report becomes a closed loop with no external referent. The user rationalises post-hoc, the formula updates toward the rationalisation, and the next round of self-report is biased by the formula&amp;rsquo;s previous output. The cure for that is to keep the rubric external: next-morning HRV, RHR shift, sleep architecture. Numbers the user is not consciously writing down.&lt;/p&gt;</description></item><item><title>Trading a 1.3 GB Bookmark Manager for 17 MB</title><link>https://dzarlax.dev/articles/trading-a-1.3-gb-bookmark-manager-for-17-mb/</link><pubDate>Wed, 13 May 2026 00:00:00 +0000</pubDate><guid>https://dzarlax.dev/articles/trading-a-1.3-gb-bookmark-manager-for-17-mb/</guid><description>&lt;p&gt;I had been ignoring it for a while: every time I looked at &lt;code&gt;docker stats&lt;/code&gt; on my Hetzner VPS, Karakeep was the heaviest container by a wide margin. A 7.6 GB box, 25 services, and one Node app taking &lt;strong&gt;1.32 GB&lt;/strong&gt; of resident memory for what is, in my use, a glorified link list with screenshots.&lt;/p&gt;
&lt;p&gt;Available RAM had drifted down to &lt;strong&gt;1.4 GB&lt;/strong&gt;, swap was pinned at 2.0 / 2.0 GB, and Postgres (capped at 768 MB) was hitting 61% utilisation. Nothing was on fire, but the margin had stopped feeling like a margin.&lt;/p&gt;</description></item><item><title>How a Sleeping Terminal Cost Me $1,000 Overnight</title><link>https://dzarlax.dev/articles/how-a-sleeping-terminal-cost-me-1000-overnight/</link><pubDate>Fri, 08 May 2026 00:00:00 +0000</pubDate><guid>https://dzarlax.dev/articles/how-a-sleeping-terminal-cost-me-1000-overnight/</guid><description>&lt;p&gt;Picture this: you&amp;rsquo;re working on a project, using Claude Code to refactor a massive monorepo. Evening comes, you close your laptop lid, and in the morning you wake up to a &lt;strong&gt;$1,025&lt;/strong&gt; API bill — even though you had strict spending limits set up in your billing dashboard.&lt;/p&gt;
&lt;p&gt;That&amp;rsquo;s exactly what happened to me. After digging through the logs, I reconstructed the timeline and found the root cause. Spoiler: the culprits were background daemons, infinite agent loops, and — ironically — the prompt caching mechanism itself.&lt;/p&gt;</description></item></channel></rss>