Aditya Dutt Pandey

Building melon · 2026

Published · 8 min read

335 commits in eight days: how I built a coding agent, and what I had to undo

The build log of melon, my coding agent. The first bug that decided the architecture, the day I deleted my own guard rails and had to put one back, a review pipeline I cut to the bone and rebuilt, and what running it on tunyt every day does and doesn't tell me.

Every coding agent I tried ended its runs the same way, with "done". It was said with total confidence, and some of the time it was wrong.

I didn't need a smarter model. I needed an agent I could believe. That one requirement turned into 335 commits in eight days, and it's melon. This is the build log, in the order it happened, including the parts I got wrong.

Why proof is the whole design

Proof is expensive. Running checks costs time, a second model reading the diff costs tokens, and verifying a claim costs more tokens again. An agent that proves its work will be slow and costly unless something else gives.

So melon is really two halves. One half makes the claims checkable: checks, an independent review, a lookup of every file it mentions. The other half makes that affordable: a context that stays small, a cache that hits, models matched to the job. Every decision below belongs to one half or the other.

Day one: the bug that decided the architecture

The first day was the skeleton, twenty-nine commits. An agent loop, adapters for the Anthropic and OpenAI wire formats, role-based model routing, a task state machine and a verification gate with repair cycles.

The first bug I found was the worst one. Shell commands that needed confirmation were being approved silently. Nothing had been asked, and nothing had been refused.

It decided where safety lives. Every tool call, whether it comes from the main agent, a sub-agent or a parallel worker, passes through one function. Guard rules, workspace confinement, approvals and the OS sandbox all hang off that single door. A rule that can be skipped by taking a different path isn't a rule, and I had just watched one get skipped. Approval fails closed now.

Day two: walls and cheaper context

October 14 was ninety-six commits, and they split into two themes.

Walls. File tools confined to the folder you started in. Shell commands scanned for paths before they run. A macOS sandbox under both. Per-repo trust, so a cloned repo can't switch on code execution. Read-before-edit. And a citation check that looks up every path:line in the final answer on disk.

That last one is a few dozen lines of plain code. It catches a whole class of confident wrongness for nothing, and it taught me to look for the dull deterministic fix before reaching for another model.

Cost. An agent run sends the whole conversation again on every call, so a tool result isn't paid for once, it's paid for on every call after it. That made the context the thing to fix. The model now sees only the lines of a file it hasn't seen, or a diff if the file changed. Big results go to an archive with an id the model can recall. Search is ranked and symbol-aware, so it can read one function and not a whole file. I also cut the per-task token budget from 1.5M to 300k, because a tight budget made me design for it.

Day three: I deleted my own guard rails

By October 15 melon had a lot of rails: call caps, a forced scout before every task, reference retries, aggressive clearing of old results. I'd added each one for a reason.

Then I copied the shape of the pi agent: seven plain tools, a tiny prompt, files read whole. I measured it against what I'd built, and many of my guards were costing more than they saved. That became "pi mode", and it's the default now.

It didn't go only one way, though. Within the same day, the replay showed 3.4 times the input tokens when old results were never cleared. Clearing came back, later and more carefully. So the lesson isn't "fewer rails". It's that every rail has to pay rent, and the only way to know which ones do is to measure each one.

The measuring tool is a replay: a scripted "model" that makes the same calls in the same order whatever the harness does, so any difference between two runs comes from the harness. It needs no API key and gives identical numbers every time. It was the most useful thing I built that week, because it turned arguments about my own design into numbers.

The review pipeline: cut to the bone, then rebuilt

The first version fanned out to many reviewers. Then a real run showed each sub-agent spawning its own challenger, which cost 80k tokens and four minutes. I cut it down to one reviewer and one verifier on a cheap model.

Over the next three days it grew back, with structure this time. A review can target the working tree, the last few commits, a branch or a PR, including one that isn't checked out. A contracts reviewer follows a changed value from producer to consumer. A verifier takes six claims at a time, so each one gets real turns.

The idea that made it work is that a finding is a claim, not a result. Early reviews read like confident fiction, with plausible reasoning about code that didn't behave that way. So a second agent now tries to disprove each claim. A confirmed HIGH is run in a throwaway copy of the change to see the defect actually happen, and one that won't reproduce is capped at MEDIUM with the attempt shown beside it. A finding that cites a file that doesn't exist is dropped before you ever see it.

What pushed me to build the reproduction step, on October 18, was a head-to-head with Claude Code's review on one PR. One PR isn't a benchmark and I'm not treating it as one. It did show me exactly where my reviewer was cheap to fool.

This is the pattern across the whole week: cut a design to what you know is true, then add back only what a real run proves is missing.

Memory: the regex found nothing

My first version learned by matching phrases like "always" and "never". The rules I actually give a tool are casual, like "commit in parts pls", and a regex found none of them.

What worked was reading each reply next to the message it replied to, so "no, not this" or "yes, like that" becomes a lesson tied to its request. The lessons go into the repo's own AGENTS.md, where a human can read, edit and commit them. melon stores only what you told it and what verified runs changed, never its own opinions about your code, because opinions are what drift.

The scars

None of these made a good commit message, and all of them are in the history.

  • A 39-minute wait on an approval prompt failed the run the moment I approved, because the wait counted against the time budget. Time spent waiting for me is now excluded.
  • A compaction lost items 6 to 10 of a pasted bug list, and they were simply gone. Compaction now appends everything it replaces to a transcript file.
  • A 53k-token prompt had its sub-agent report and AGENTS.md reads wiped by pruning. The model read them again and the cache broke. Clearing now waits until the prompt is large, and folder rules are re-attached after a prune.
  • A routing bug swapped the model I'd pinned for the strong chain whenever it escalated.
  • An on_error hook existed for days and nothing ever fired it.
  • A partial git add shipped a syntax error while another session was editing the same checkout.
  • I flip-flopped on the full-screen UI three times. It looks great, and it breaks native selection and scrollback copy.

Most of these share a cause. The code worked in the case I'd imagined, and a real run found the case I hadn't.

What running it on tunyt tells me, and what it doesn't

I've been running melon on tunyt every day, with MiniMax M3 doing the work, to find out whether the harness holds up. It's working really well for me. My commit stats on the repo are what you'd expect from that: 2,505 commits, 6,282,563 additions and 2,885,876 deletions, the top contributor.

I'll be careful with those numbers, because they're easy to over-read. Commits and lines measure volume, not quality, and they cover everything I did on tunyt, not only what melon wrote. They can't tell you how much better it is than anything else. What I can say is that I trust it enough to run it daily on the repo I care most about, and that's a different kind of evidence from a benchmark.

What I'm not claiming

No head-to-head benchmark against other harnesses has been run, so there's no "better than X" number. The cross-model task bench shows 22/22 for one model and 4/22 for most of the rest, which looks like quota blocking and not ability, so I'm leaving it out. The planted-bug review bench has two saved runs on two tiny cases: one run missed the bug, and the next found it with no noise on the control case. That's fair to say and unfair to turn into a percentage. And several defaults were tuned on a single repo, so they're measured there and not universal.

To get stronger numbers I'd rerun the model comparison on a day with free quota and add more planted-bug cases. Both are real work, and both would make this story better.

What I'd take from it

Put the boundary in code, and keep it in one place. Reach for the dull check before the clever one. Measure each rail, including the ones you're proud of. And when a design goes wrong, cut it down to what you know is true and add back only what a real run demands.

The best thing the eight days taught me is that an agent should never be the last one to read its own work.

← All writing