Devlog 4 - button that did nothing, and a notebook helper
Two things this session. One was a bug that taught me the difference between “out of memory” and “out of time,” and a whole new feature for my robotics team.
WeekLog has a “Download all media” button that zips up every photo the team’s uploaded. It just… didn’t work. No error, no download, nothing. The worst kind of bug because I had no idea where the problem lied
First real clue came from the browser network tab: the request was coming back 503, and the error page was Cloudflare’s, not my app’s. It meant my code wasn’t throwing an error, the platform was killing my worker before it could respond. So the frontend was hiding a failure it should have shown, first I made it actually show me the error instead of just letting it fail
Then the real chase. My worker was loading every file fully into memory and building the zip all at once, so I assumed it was running out of memory. I rewrote it to stream the zip instead, pulling one file at a time. Felt good. Still broke. So I tailed the live worker logs and got the actual smoking gun: “outcome”: “exceededCpu”. It wasn’t memory at all. The media set is about 404 MB, and just computing the checksums to zip that much data is more compute than a free-tier worker gets per request. Streaming fixed the memory ceiling and I still hit a completely separate CPU ceiling behind it. You genuinely cannot zip 404 MB inside one free worker call.
The fix was to stop trying. Instead of the worker building the zip, it now sends a tiny manifest (just a file list, no actual bytes, comes back in ~2.4 seconds) and the browser pulls each file and builds the zip locally. Worker work stays tiny, it scales to any size, and it stays free. The lesson I’m keeping: don’t assume the first plausible cause is the only cause. “Streaming fixed it” was true and the thing still broke.
The Notebook Prep pipeline. The bigger build. FGC has an engineering-documentation award judged on the journey a team took building their robot, and WeekLog already has our whole logged season sitting in it. So I built a pipeline that mines that logged data into notebook-prep material: per-subsystem timelines, a gap analysis that flags where our documentation is weak against what judges actually look for, a decision-log extractor, and a draft scaffold.
The rule I built the whole thing around: it is a super-helper, never a ghost-writer. Every output is deliberately un-submittable, it hands you your own logged words as raw material plus [NEEDS: …] prompts where a human has to add the reasoning and the numbers. It never writes notebook prose and never invents a fact. A notebook that reads like an AI wrote it loses that award, because the whole point is proving the humans did the thinking. So the tool audits and prompts, it doesn’t author.
The part I’m proud of architecturally: there’s no AI running in the app at all, and no ongoing cost. The deterministic stuff (timelines, coverage counts) is plain worker compute, and the actual reasoning is done by me in Claude Code following a runbook, then published into the app through a secret-gated write-back route. The app just renders whatever got published as red/amber/green cards and checklists. It doesn’t know or care that AI produced a report. Zero runtime AI cost, and the reasoning is grounded in a reference brief on what FGC judges reward so it’s not just generic advice.
Shipped and live: the ZIP button works via the browser now, and Notebook Prep has all four tabs (Timeline, Gaps, Decisions, Scaffold) carrying real published content. 41 commits this session.
More to come: judge-question rehearsal generated from our actual logged work, tracking notebook health over the season, and tagging photos to subsystems at upload so the timelines get richer.
Comments 0
No comments yet. Be the first!
Sign in to join the conversation.