Test Before You Trust
My workstation is an AMD Strix Halo. It has an NPU, and the NPU can run an embedding model – embed-gemma-300m-FLM, served by Lemonade
alongside the same model on the integrated GPU. Same weights, two runtimes. Moving embeddings to the NPU is more an experiment in using available hardware than anything else. I’ve experimented with Whisper transcription on the NPU successfully with (dicta)[]; it was acceptable, slower than the iGPU, slightly worse, but functional enough that I use it and the GPU stays free for more demanding tasks. This seemed like a natural follow up when I saw it in (Lemonade)[]’s list of NPU models.
Fast Is Slow, Slow Is Smooth, Smooth Is Fast
My D&D transcription pipeline got about a third faster. I did it by taking away twenty-four of the thirty-two threads it was using, and by not using the fastest GPU in the house.
Neither of those was the plan. The plan was to throw a 5090 at it.
Fast is slow
I’ve written before
about how the session reports get made: record the Discord audio, transcribe it with speaker labels, hand the transcript to an LLM, edit the result into narrative prose. That post described a pair of bash scripts wrapping WhisperX. Since then the scripts have been replaced by a single Go binary that does the same job without PyTorch, without a Hugging Face token, and without a Python environment to rot.
The Capture Card That Wouldn't Capture
The card is a clone. Its PCI vendor ID is 0x8888 – not a registered vendor, just four eights, the fingerprint of hardware built to look like something it isn’t. lspci calls it a “Silicon Magic AVMatrix VC12 4K HDMI Capture.” It’s a cheap 4K HDMI capture card in the lineage of a Magewell Pro Capture, and it had sat dead in one of my machines since I bought it, because the only Linux driver I could find for it didn’t work.
Hard Lemonade: Three Fixes to Get Local AI Pouring on AMD
Running a local LLM server is the easy part. Getting three separate pieces of infrastructure to agree that a model is downloaded, reachable, and worth waiting for is where the afternoon goes. Over the past two weeks I shipped three fixes across two open-source projects to get AMD’s Lemonade
serving models behind the Olla
proxy on my Strix Halo box. None of them was hard in the algorithmic sense – the diffs are a struct field, a config key, and a prepended path. They all came out of the same goal: point Olla at Lemonade on a Radeon and get a chat completion back.
Smoke: Black-Box Route Testing the Router Gates Itself
Every unit test was green. The page returned 502 anyway.
The route was a treasure generator. Its store had a thorough test suite, all passing, because the test built the store the way the test knew to build it – with the database pool wired in. Production built it differently: a copy-paste in the route setup left the pool out, the store carried a nil handle, and the first query dereferenced nil. The handler panicked, the connection dropped, the reverse proxy turned that into a 502. No test caught it, because no test exercised the wired route against a running server. The tests checked the parts. Nothing checked that the assembled thing served.
The Layers That Didn't Hold
A few weeks ago I wrote
that defense in depth for AI agents means layers, not walls: screen untrusted content before the model acts on it, sanitize what comes back out, and never trust the data flowing through. Clean theory. Then I went back and read the code in Herald
that was supposed to implement those layers.
Several of them didn’t hold.
Herald is my feed reader. It pulls RSS and Atom from across the internet, runs each article through a local security model before anything else touches it, scores the survivors for relevance, and announces the interesting ones. Every feed item is untrusted content aimed at a model. That’s the whole premise of the defense-in-depth piece, and it’s exactly the threat I built Herald to study. What follows is the v0.2.0 hardening pass – the bugs the theory missed, and a couple of ideas that worked.
The LiteLLM Supply Chain Attack: A Homelab Postmortem
On March 24, 2026, the LiteLLM PyPI package was compromised. Versions 1.82.7 and 1.82.8, published by an account labeled TeamPCP, contained malicious code. I had LiteLLM running in my homelab as a routing layer between local AI clients and several model backends. This post is the postmortem: what I was running, what the exposure actually was, why I removed LiteLLM rather than just upgrading, and what the incident clarified about supply chain risk in homelab AI infrastructure.
Defense in Depth for AI Agents
The security conversation around AI agents has mostly focused on two things: keeping agents from hurting the host system, and keeping malicious tools out of the supply chain. These are real problems. Cisco documented
how OpenClaw leaks credentials and executes arbitrary shell commands. Projects like NanoClaw
respond by running agents in containers where bash commands can’t reach the host. Zencoder’s MCP survival guide
catalogs supply chain attacks against MCP servers and recommends pinning git tags and auditing source.
Threat Modeling a Persistent Memory Store for AI Agents
Persistent memory for AI agents solves a real problem (the goldfish-with-a-PhD problem) but it introduces a new one: a high-trust, cross-session, cross-agent data store sitting inside the LLM’s context loop. Every recall is content that flows into a prompt. Every store is content that came from somewhere – sometimes the user, sometimes the model, sometimes a tool result that originated externally.
That’s a threat model worth writing down before the data store grows up. This post is the threat model for memstore – the persistent memory system I built for Claude Code – and the controls I’m applying or planning.
Self-Improving Recall: A Feedback Loop for AI Memory
A memory system that ranks facts the same way forever is dead weight. The signal that
actually matters – did this fact help, or did it waste context – only exists during a
real conversation. Memstore’s feedback loop captures that signal in-session and feeds it
back into recall ranking, so the system gets better at surfacing useful knowledge the
more it’s used.
The problem: static recall is stale recall
Memstore’s baseline ranking uses static signals – IDF, project boosts, semantic similarity, recency, surface-aware multipliers for project-level facts. All of them are derived from the fact itself, the query, or the static metadata around them. None answers the real question: when memstore injected this fact last time, did it help the agent or did it just crowd out something better?