2026-06-13 08:00:00
I always felt a little bad for the ghosts in Pac-Man. They patrol the maze, they corner the guy, and then he eats a glowing pellet and suddenly they're the ones running for their lives. So I built a small game where you finally get to play the other side.
Pac-Man has its own AI, and your job is to catch him before he clears the maze. The twist is the same one that always ruined my day as a ghost: if he eats a power pellet, the tables flip and he hunts you for a few seconds. Then you run.
You can play the game here. Have fun!
<img width="676" height="867" alt="Image" src="https://github.com/user-attachments/assets/80319217-7cd2-432e-8006-01ff5cefef06" />
2026-05-29 08:00:00
TL;DR: My meter dropped offline for ~13 days. Home Assistant's long-term stats came back wrong — a -4,500 kWh bar, a phantom 862 kWh solar spike. The dashboard is a view. The truth is in the
statisticstable. You fix it with oneSELECTto find the damage and oneUPDATEto undo it.
For a while now, my energy dashboard in Home Assistant reports that my house had produced negative 4,500 kWh in April. It was finally time to fix that.
<img width="1080" height="1527" alt="Image" src="https://github.com/user-attachments/assets/01335840-93b5-4d80-ae45-1bb972650269" />
Each sensor stores two values per hour in the statistics table. state is the raw meter reading. sum is HA's cumulative total, computed from the deltas between readings. When a total_increasing sensor blinks out and back, sum gets corrupted — but state is almost always still fine. So you trust state and rebuild sum to match.
Stop HA and back up the DB first — you're editing prod. Then: find the broken row, read its numbers, plug them into the fix.
Get the metadata_id, then dump the rows around the glitch. Select start_ts too — those raw unix timestamps are what you'll paste into the fix:
`sql
SELECT id, statisticid FROM statisticsmeta WHERE statistic_id LIKE '%balkonkraftwerk%';
-- -> 142
SELECT id, startts, datetime(startts,'unixepoch','localtime') AS t, state, sum
FROM statistics
WHERE metadataid = 142
AND startts BETWEEN strftime('%s','2026-05-04') AND strftime('%s','2026-05-05')
ORDER BY start_ts;
`
You're hunting for the row where the story breaks. There are two shapes it takes, and they want different fixes.
state flat, sum jumps)The output:
id start_ts t state sum
...
2643324 1777917600 2026-05-04 20:00:00 862.271 1031.552 <- last sane row
2643402 1777921200 2026-05-04 21:00:00 862.271 1893.823 <- sum leapt, state didn't
state is identical across both rows, so no energy was actually produced. The damage is the jump in sum:
phantom = 1893.823 - 1031.552 = 862.271 (the bad delta)
from id = 2643402 (first row carrying it)
sum is cumulative, so that 862.271 rides along in every later row too. Subtract it once, from the bad row onward:
sql
UPDATE statistics SET sum = sum - 862.271
WHERE metadata_id = 142 AND id >= 2643402;
state advanced, sum restarted at 0)Same SELECT, different sensor (155, the grid meter), around the outage:
start_ts t state sum
1775044800 2026-04-01 14:00:00 4922.912 4792.995 <- last reading before the gap
1776171600 2026-04-14 15:00:00 5127.167 0.382 <- meter's back, sum reset to ~0
Two things broke: sum fell off a cliff to 0.382, and the 13 days between are simply missing. But state kept counting through the outage, so it tells you the truth. Derive everything from those two rows:
real consumption during gap = state_after - state_before = 5127.167 - 4922.912 = 204.255
where sum SHOULD be at 14.04 = sum_before + that = 4792.995 + 204.255 = 4997.250
offset to re-base later rows = should_be - actual = 4997.250 - 0.382 = 4996.868
Step one, lift every post-reset row back onto the real baseline (using the gap's end timestamp, 1776171600):
sql
UPDATE statistics SET sum = sum + 4996.868
WHERE metadata_id = 155 AND start_ts >= 1776171600;
Step two, draw a straight line across the empty gap. The CTE just holds the two endpoints — start (t0=1775044800, s0=4792.995) and the now-corrected end (t1=1776171600, s1=4997.250) — and fills an hourly row for each step between:
sql
WITH RECURSIVE v(t0,t1,s0,s1) AS (SELECT 1775044800,1776171600,4792.995,4997.250),
hours(ts) AS (SELECT t0+3600 FROM v
UNION ALL SELECT ts+3600 FROM hours,v WHERE ts+3600 < v.t1)
INSERT INTO statistics (metadata_id, created_ts, start_ts, sum)
SELECT 155, h.ts, h.ts, v.s0 + (v.s1-v.s0)*(h.ts-v.t0)*1.0/(v.t1-v.t0)
FROM hours h, v;
Restart, re-run the SELECT, confirm the line is boring again.
<img width="3422" height="1786" alt="Image" src="https://github.com/user-attachments/assets/12775462-3ed8-4399-885c-f26e6ea24af8" />
I told you it was one UPDATE. I was wrong, and the next morning the dashboard told me so. The -4,500 bar was back. The 862 kWh spike was back. Same size, new date: today.
Nothing new had broken. My own fix had bounced back.
Here's what I'd missed. statistics isn't the only table. There's a second one — statistics_short_term, five-minute rows that HA rolls up into the hourly statistics table once an hour. And it still held the old, pre-fix cumulative sums. So every hour, HA dutifully re-aggregated the garbage and clobbered my correction, dumping the difference straight into the current hour. I wasn't fixing the data. I was fixing a cache while the source of truth quietly overwrote me.
Worse: HA was running the whole time. The recorder keeps short-term state in memory and flushes it on shutdown — so even my careful edits got stomped the moment it wrote back. Editing a database underneath a live application is like editing a file in vim while another process truncates it. Whoever writes last wins, and it isn't you.
So the boring line I buried up top — stop HA first — turned out to be the whole game. Not a footnote. The rule.
Stop the core properly. On HAOS that's ha core stop — and do it over real SSH, not the browser terminal, which is served through the frontend, dies with it, and locks you out. (Ask me how I know.) Then fix both tables:
sql
UPDATE statistics SET sum = sum - 862.271 WHERE metadata_id = 142 AND id >= 2643402;
UPDATE statistics_short_term SET sum = sum - 862.271 WHERE metadata_id = 142;
Before you start HA back up, check the seam: the highest sum in short-term should land right where your latest statistics row sits, with no cliff between them.
sql
SELECT MIN(sum), MAX(sum) FROM statistics_short_term WHERE metadata_id = 142;
One nuance that explains why the first pass looked fine: short-term only keeps the recent stuff, ~10 days. If the hour you're editing is older than that, it's already purged and statistics is all you need. My April gap was ancient enough to ignore it. The recent spikes weren't — and that's exactly what came back to bite me.
2026-05-06 08:00:00
I recently watched a video that put a name on something I'd been feeling. The author splits an LLM's context window into two zones. There's the smart zone, where the model is sharp, and the dumb zone, where attention drops off and the model starts forgetting what you told it five minutes ago. The cutoff sits somewhere around 100k tokens. It doesn't matter how big the advertised context window is.
This matters because coding agents will happily walk you straight into the dumb zone. A modern agent burns through tokens fast. A few file reads, a long debug session, a sprawling test run, and you're at 100k before lunch. Meanwhile vendors keep advertising windows of 200k, 1M, even 2M, as if those numbers represented a usable working set. They don't. Studies like RULER and Chroma's report on context rot show that effective context is a fraction of the advertised number, and that performance degrades gradually as you fill the window.
Large context windows are mostly a marketing number. The architectures behind them work, but they paper over a problem the underlying attention mechanism doesn't really solve. The number on the box gets bigger every release. The usable part doesn't keep up.
Modern agents are getting smart about this. Tools like Claude Code now auto-compact: when the session gets long, the agent summarizes the history and starts fresh. That helps. But auto-compaction kicks in after you've already spent time in the dumb zone, and the summary is itself produced by a model that's already degraded. Better than nothing, but I'd rather avoid the situation altogether.
What I do is open a new session and pass it a spec I wrote myself. That's a much higher signal handoff than any automated summary, because I get to decide what matters going forward. It's the breadcrumb approach applied to agents. Leave an artifact that the next session, or the next person, can pick up cleanly.
You can take this further. Projects like obra/superpowers and mattpocock/skills structure entire agent workflows around small, named artifacts. PRDs, plans, skills, sub-agent handoffs. Each one is a way to keep the working session in the smart zone by deliberately moving information out of the session into something the next session can read.
So I treat my context window like a budget. I assume only the first chunk is really working for me, and everything I can move out of the live session and into a written artifact is one less thing for attention to fight over.
2026-02-13 08:00:00
n8n-nodes-open5e is an n8n community node that lets you access D&D 5th edition SRD content from the Open5e API in your n8n workflows.
The Open5e node provides access to 12 different D&D 5e resources through the Open5e API. Each resource supports three operations:
Create random encounters by fetching monsters filtered by challenge rating:
5
wotc-srd
Build a Discord bot that looks up spell information:
={{ $json.spellName }}
Search for magic items and weapons by name:
={{ $json.query }}
10
This is my first n8n community node. Contributions are welcome! Please feel free to submit a Pull Request or open an issue if you encounter any issues.
2026-02-11 08:00:00
From my notebook:
Brains are pattern recognition machines.
I seek structure, sometimes meta-structure.
I try to structure how I structure things.
Projects, stories and adventures often only become apparent when they are in the past.
They evolve naturally, organically. Starting a project can result in something completely different. Is there a structure in that?
I am trying to find structure again.
Life is chaotic, and that's okay.
I had this on my mind for quite some time. I'm trying to cope with chaos in my life. I like chaos, and I like turning chaos into order. But often, that does not work and I get frustrated.
Projects - no matter if programming, writing, planning an event or woodworking - are inherently chaotic. There is no structure in the concept of a "project". I want to think of a project as the sum of threads of actions towards a goal, and life is the sum of every project you ever started. I try to find a way to capture and grasp these "threads" - like commits on different branches of a code repository. On projects other than programming, this utterly fails.
I have to keep telling myself to be fine with the fact that life does not follow a structure. My personal takeaway is learning to recognize when I am seeking structure as a response to anxiety vs. when I'm doing it because it's actually useful.
Am I alone with this? Does this resonate with anyone out there? I'd love to hear from you.
2026-02-04 08:00:00
Long-pressing j or k (think "down" or "up" in Vim) only results in one down or up action, instead of continuous scrolling.
In a terminal, run the following command:
defaults write com.microsoft.VSCode ApplePressAndHoldEnabled -bool false
Original post: https://stackoverflow.com/a/44010683
In the MacOS settings, set "Key Repeat Rate" and "Delay Until Repeat" to the highest setting to be able to scroll much faster.
<img width="478" height="92" alt="Image" src="https://github.com/user-attachments/assets/7bf85853-377d-4727-a5c8-2766f2794e8a" />