The week in numbers, and why they don't matter much
115 commits landed across 14 active projects this week. I mention the count once, and then I want to throw it away, because commit counts are a terrible proxy for what actually happened. What happened was: a diagnostic-imaging research project went from "founding summary" to a working, audited, on-device inference pipeline. A measurement app shipped a resize/geometry bug fix that took real signal-processing reasoning to isolate. An FPGA spec got a new low-depth reference-mode design. And the automation system that watches all of this for me — the one that reads git history, App Store Connect, competitor sites, and API changelogs so I don't have to — caught itself failing, and I had to go fix the thing that fixes things.
That last part is the most interesting thread this week, so let's start there.
When your monitor lies to you by going quiet
Every Friday I get an automated TestFlight feedback report — pulled straight from the App Store Connect API, categorized, RICE-scored, checked for cross-app crash patterns. This week's scheduled run hit a 500 from Apple's servers before it retrieved a single feedback item. The pipeline aborted cleanly, wrote an empty result, and the downstream report rendered as "0 apps with feedback."
Here's the failure mode that matters: a report that says "zero feedback" and a report that says "the fetch failed" look identical to a human skimming a dashboard. Both show a zero. Only one of them means anything. A manual re-run later that day succeeded and surfaced a build-5 crash report on one of my apps that had already gone unaddressed for two weeks straight — sitting there the whole time, just not visible because the automated collector never got past Apple's error.
That's a distinction I now bake into every pipeline: "no data" and "a failed attempt to get data" must never render the same way downstream. It sounds obvious written out like that, but it's exactly the kind of bug that survives in production because on 9 runs out of 10, a genuinely empty result and a failed fetch produce the same zero-item output, and nobody notices until the 10th run hides something real.
The fix wasn't just patching that one pipeline. I'd already built a shared retry wrapper — one function, aretry, used everywhere a script talks to an LLM API or a flaky upstream service — and this incident was the forcing function to sweep it across every pipeline that still had a hand-rolled retry loop or no retry logic at all. Roughly a dozen scripts got touched: a Perplexity-based research roundup that was reporting stale "current" tools because its search window wasn't actually constrained to the last week, an SDK caller that would occasionally emit raw uncurated dumps instead of a clean digest, a social-report script that would crash the whole weekly run on a transient X API blip. None of these were exotic bugs. They were all the same bug — "assume the network call succeeds" — showing up in different clothes across a dozen independent scripts, because I'd written each one at a different point in time before I'd converged on a standard pattern.
This is, I think, the actual skill AI-assisted development unlocks here: not writing the retry logic (that's trivial), but having enough throughput to go do the boring, portfolio-wide consistency sweep in an afternoon instead of it being a six-month backlog item that never gets prioritized because no single instance of the bug looks urgent enough on its own.
A new research domain, audited end to end, in a week
The most substantive build this week was a from-scratch research project: a low-cost self-imaging diagnostic rig — essentially proving out whether a DIY optical front-end (one lens, a bracket, an LED, on the order of tens of dollars in parts) paired with an on-device vision model can do meaningful disease flagging from captured images.
What I actually spent the week on wasn't optics or app plumbing — it was the validation chain, because that's where a project like this lives or dies. I calibrated a quality gate against real labeled image data, closed out a full audit (patient-grouped cross-validation, held-out thresholds, per-condition AUC, prompt ensembling) to make sure the gate wasn't quietly overfitting to whatever data it first saw, and then ran an adversarial pass specifically looking for ways the pipeline could be fooled by synthetic degradation before I trusted it near a gate-reject decision. Only after that scaffolding was solid did I wire up the actual inference path — a Swift client talking to a small server-side model — and add a longitudinal store so repeated captures over time build a trend rather than a series of disconnected one-off readings.
That ordering matters and it's very much a research-engineer instinct rather than a developer instinct: build the measurement-validity argument first, ship the feature second. AI tooling didn't remove that step — if anything it made it easier to skip, because generating a plausible-looking inference pipeline is now nearly free, and the temptation is to declare victory the moment something runs. The discipline is in refusing to call it done until the audit trail says the gate behaves the way you claimed it would on data it hasn't seen.
What automated scanning caught this week
Two smaller findings from the portfolio-wide monitoring worth noting, because they're a good illustration of what these scans are actually for.
First: an academic-metadata API I use for a market-signals scanner quietly moved to mandatory API-key authentication, breaking a scanner that had been treating it as free and keyless. Small thing, but exactly the kind of change that goes unnoticed for weeks in a script nobody's staring at daily — the whole point of running an automated cross-API changelog check is to catch these before they've been silently broken long enough to matter.
Second: a competing OBD2-diagnostics app's marketing site flipped its Android listing from "coming soon" to live, with pricing published for the first time, in the same week. A weekly automated competitive scan caught the change within days of it happening — which is the actual value of running these checks on a schedule instead of manually remembering to go check competitor sites every so often. You don't get to decide when a competitor ships; you just get to decide how fast you find out.
The through-line
None of this — the imaging research, the geometry fix in the measurement app, the FPGA reference-mode spec, the retry sweep — required me to write much code by hand this week. What it required was deciding what to validate, in what order, and catching the places where my own automation was quietly lying to me about its own health. That's the actual job now: framing the problem, setting the bar for "this is trustworthy," and letting the implementation layer keep up. The system that watches my systems still needs watching — but at least now, when it fails, it fails loudly.