{"slug": "block-zero-oh-no-claude-kiro-and-i-over-engineered-the-throwaway", "title": "Block Zero: Oh, no! Claude, Kiro and I over-engineered the throwaway.", "summary": "An engineer building Porch Light, an AI agent that monitors city public meeting agendas, found that AI coding agents Kiro and Claude over-engineered a throwaway spike, adding a byte-identity test to a folder marked for deletion. The engineer, who directs agents rather than writing code, learned that agents reason locally and lack the instinct to stop, so they must manufacture checkpoints to catch wrong assumptions early. The spike validated the stack but revealed five discrepancies in the architecture, including AgentCore naming deployments itself and a redaction processor that strips document content from logs.", "body_md": "A lesson in overcorrection, from an AI-assisted builder who is scared stiff of shipping spaghetti and slop.\n\nI am building Porch Light, an agent that watches one city's public meeting agendas for one person. I do not type the code. I direct, Kiro builds, Claude reviews, and I validate and decide.\n\nBlock Zero was supposed to answer a yes-or-no question: does the stack work?\n\nCan I invoke a model? Can I run a Strands agent? Can I deploy it to Bedrock AgentCore? Do my logs land where I think they land?\n\nIt should have been a two-hour spike. Prove the stack, commit, move on.\n\nInstead, it took a little over a build day.\n\nBy the end of it, Kiro was writing a byte-identity test to protect a file inside a folder I had tagged `[THROWAWAY]`\n\nthat morning.\n\nAnd I had approved it.\n\nMy task list has that tag for code that does not survive. I invented it specifically so I would stop polishing things I was about to delete.\n\nNeither agent asked why a folder marked for deletion needed a test at all. Kiro wrote it. Claude reviewed it against my own security rules and approved it. Both were correct about the work in front of them.\n\nNeither one was watching the tag.\n\nI was watching the clock.\n\nSo, in the middle of the block, I typed:\n\nWhy is Block 0 going so slow? Did we over-gate?\n\nThat question is the reason this post exists.\n\nThe lesson was not that the agents were doing bad work. It was almost the opposite. They were doing defensible work, locally and rigorously, without asking whether that level of rigor belonged there at all.\n\nThat question was mine.\n\nWhy spike at all in a hackathon? The whole genre is move fast and find out. Just start building and see what happens.\n\nI agree with that right up to the point where nobody in my setup is typing the code.\n\nDevelopers who write their own code talk about friction. Something feels wrong under your hands, the shape of it fights you, and you stop before you can say why.\n\nI have never had that.\n\nI came to this directing agents, so I have never built that physical instinct, and the agent does not have it either. It will build confidently on a wrong assumption for hours because it reasons locally. It is not holding the deadline, and every individual step it takes can be correct.\n\nMine did exactly that.\n\nSo I have to manufacture the stop.\n\nThat is what a spike is for me: a short experiment, a pass or fail written down before I start, and a chance for the wrong assumption to surface while it is still cheap.\n\nBecause the cost of a wrong assumption is not flat. Finding out at Block 5 that AgentCore does not work the way I designed for means rewriting everything already stacked on top of it, with the deadline closer and my patience thinner.\n\nSpike B was the AgentCore deploy. One task in the plan. In practice, it was \"learn a product you have never used,\" and the product disagreed with my architecture document in five places:\n\n`PYTHON_3_14`\n\n.`@app.entrypoint`\n\ngenerator yielding events off `stream_async()`\n\n.`deploymentType: codeZip`\n\n. The generated config is a `runtimes[]`\n\narray with a `networkMode`\n\nfield.`/porchlight/dev/extractor`\n\n. AgentCore names them itself and does not ask.\nI did not type the architecture document either, but I approved every line of it, so the five wrong calls were mine.Kiro stopped and reported each discrepancy instead of quietly adapting.\n\nThat is exactly the behavior I wanted.\n\nFive corrections, all cheap now and expensive at Block 5.\n\nThat part I would do again.\n\nThe deploy also exposed the finding that justified the whole block.\n\nPorch Light reads public documents. Those documents go through a model. My logging module has a redaction processor that strips document content out of log events before they reach CloudWatch, because a security rule in my steering files says logs never contain document text.\n\nTwenty-eight tests were passing.\n\nProperty tests over generated inputs. Case-insensitive key matching. Recursion into nested dicts and lists.\n\nGreen.\n\nThen the deploy succeeded, and we inspected CloudWatch.\n\nThe log format was AgentCore's, not the one I had in mind or had written into the spec.\n\nThe spike had used the framework's built-in logger instead of importing the designed logging module.\n\nSo the redaction processor, the size cap, the context binding: none of it had ever executed inside the runtime it existed to protect.\n\nThe tests proved the code was correct.\n\nThey proved nothing about whether the code was there.\n\nKiro's report called this \"expected.\" It was expected. It was also the largest hole in the block, and the word *expected* is exactly how a finding turns into a footnote.\n\nThe fix took four log lines and a redeploy.\n\nThen CloudWatch showed the schema, a `[truncated:1000]`\n\nmarker on an oversized field, a `[redacted:document_content]`\n\nmarker on a document key, and, unexpectedly, a botocore credential message carrying my `run_id`\n\nand `component`\n\n.\n\nThird-party library logs were inheriting my context inside the deployed runtime.\n\nThat is when the logging design started doing something instead of describing something.\n\nA control that has never run in the environment it protects is not a control.\n\nIt is an intention with tests.\n\nTo get the logging module into the deploy package, we vendored it: a second copy of `log.py`\n\nliving inside `deploy/spike_b/`\n\n, with a note in the docstring to keep it in sync manually.\n\nManual sync of a security control is not a control either.\n\nSo we wrote a sync script that copied the file verbatim, plus a test in the default suite asserting the two files were byte-identical. Drift would fail within one test run.\n\nThen we found that `uv.lock`\n\ndid not govern the deployment at all. AgentCore resolved dependencies server-side from the deploy package's own `pyproject.toml`\n\n, and my two manifests had already drifted apart.\n\nOne said `structlog>=26.1.0`\n\n. The other said `>=24.4.0`\n\n.\n\nBoth were unpinned floors on the library whose behavior supported my security control.\n\nSo: exact pins, and another test asserting the pins matched the lockfile.\n\nEvery individual decision was defensible.\n\nEvery individual decision was also protecting `deploy/spike_b/`\n\n, a folder that stopped existing when Block Zero closed.\n\nI have a rule that says **stub, do not build**. My PRD uses `MUST`\n\n, `STUB`\n\n, and `NEVER`\n\nto control sequence and scope.\n\nBlock Zero treated everything as `MUST`\n\n.\n\nThat was not an agent failure.\n\nThat was mine.\n\nI do not want judges, my peers, or me a year from now opening the repo and finding something thrown together without care. I want to be taken seriously as a builder, and the fastest way to lose that is one look at the code.\n\nI also came to this from operations, where the instinct is to build a control for the thing that happens once in a thousand times, and where nobody gets credit for the incident that did not happen.\n\nThat instinct is often right.\n\nIt also erects its own barriers.\n\nHere it cost me build hours on a spike and consumed tokens like Jabba the Hutt working through a bowl of Klatooine paddy frogs.\n\nNo bueno.\n\nThe complicated part is that more than one thing is true at once. The rigor is not only fear. The PRD, and the `MUST`\n\n, `STUB`\n\nand `NEVER`\n\nlabels, are how I direct. They are the vision made specific enough for an agent to build from. Stub, do not build is a decision about sequence, not a polite way of never doing something.\n\nI want the output to be good and I want it to be recognizably mine.\n\nBoth of those are true, and neither one of them tells you when to stop.\n\nThis is the part I keep turning over.\n\nVendoring the module was the available way to get it into the deploy package. Replacing a manual sync promise with a byte-identity test is better engineering than trusting a comment. Pinning a security-relevant dependency exactly is better than an unpinned floor.\n\nAsk any of those questions in isolation and the answer is yes: do the rigorous thing.\n\nNobody asked the question that was not in isolation:\n\nShould this folder be getting this treatment at all?\n\nBoth agents were reasoning locally and reasoning well.\n\nKiro proposed correct fixes to problems that were there. Claude reviewed them against my security rules and approved them.\n\nNeither stepped back to check the tag on the folder, because neither was watching the calendar with any stake in it.\n\nI was.\n\nI had a submission date and a calendar I was already behind on.\n\nThat is not a story about agents being bad at their jobs. It is a story about what the human is for in this setup.\n\nI direct. The agents generate. I validate and decide.\n\nI have said that a lot. Block Zero was the first time I could point to the specific sentence that only I was positioned to say.\n\nThe durable version became a **rigor budget**:\n\nI would rather encode the question than have to keep remembering to ask it.\n\nOne more from that block, and my favorite.\n\nMy AWS account ID was sitting in three tracked files, and the repo goes public for judging. An account ID is not a credential. It is closer to a street address: harmless alone, useful to someone aiming.\n\nSo we gitignored the deploy state file, gave the target config the `.env`\n\ntreatment, redacted the number out of the spec prose, and ran `git-filter-repo`\n\nover the whole history.\n\nThe verification pass failed. The check kept finding the account ID.\n\nIt was in the documentation of the scrub. The number had been written into the prose explaining what we were removing, so the search kept hitting the sentence describing the search.\n\nBlock One was the product itself: the adapter that reads Ventura's agendas.\n\nIt went fast, partly because Block Zero had already found everything AgentCore was going to disagree with.\n\nWe put a ten-minute compliance gate at the front. Read the city's `robots.txt`\n\nand terms of use before writing a single requirement.\n\nTen minutes bought three things.\n\nVentura is two vendors, not one: a CivicPlus front door over a Granicus agenda system, different companies and different hosts.\n\nThe Granicus host's `robots.txt`\n\nreads `Disallow: /`\n\nfor everyone, so it is off limits. I obey that even though `robots.txt`\n\nis a convention rather than law. A tool whose whole claim is trustworthy reading of public records cannot quietly override a public body's stated preference.\n\nAnd the only structured API in the setup sits on the host we are not allowed to touch, which killed the shortcut I was hoping for.\n\nThen the block ran clean.\n\nFifty-seven tests passing.\n\nProperty tests on the parser: never crash on malformed rows; every emitted meeting carries a valid date and at least one document URL; unparseable rows get surfaced instead of dropped.\n\nAll true.\n\nAll green.\n\nThe last task in the block was a hand-check: take a known week, pull what the parser produced, open the live site, and compare by eye.\n\nEvery single meeting had its documents listed twice.\n\nThe rows linked each file from both an icon and a text anchor, and the parser faithfully collected both.\n\nThe property tests could not catch it because every property they asserted was satisfied.\n\nA duplicate URL is still a valid URL. The meeting still has a date. Nothing crashes.\n\nGreen suite. Wrong output.\n\nThe only thing standing between that bug and Block Two was a person looking at a screen.\n\nIt was the same shape as the redaction gap, produced by a different mechanism.\n\nThe redaction tests proved that the control worked but not that it was deployed.\n\nThe parser tests proved that the output satisfied its properties but not that the output was right.\n\nA test answers the question you thought to ask when you wrote it.\n\nProperty tests answer a wider version of that same question.\n\nNeither decides whether you asked the right question.\n\nTwo blocks left me with three habits, and they cost wildly different amounts.\n\n**The compliance gate:** ten minutes before implementation. It killed a bad architectural shortcut before I built around it.\n\n**The hand-check:** twenty minutes after the automated suite. It caught a bug a hundred more assertions about the wrong properties might not have found.\n\n**The rigor budget:** hours learned the expensive way. Full rigor for things that survive, working rigor for features, spike rigor for throwaways.\n\nThe first asks whether I am allowed to build the thing the way I intend.\n\nThe second asks whether the thing I built is right.\n\nThe third asks how much engineering this piece of work deserves.\n\nThe agents can help answer all three.\n\nBut someone has to remember to ask.\n\nThat, increasingly, is what I think my job is.\n\nI came to code from the courtroom: jury services to AI builder, self-taught and learning in public. I direct, the agents generate, I validate and decide. I build the Clew Suite and a handful of civic-tech tools.\n\nI used to think the important part of that sentence was *validate*.\n\nAfter these two blocks, I think it may be *decide*.\n\n**AI Assisted. Human Approved. Powered by NLP.**", "url": "https://wpnews.pro/news/block-zero-oh-no-claude-kiro-and-i-over-engineered-the-throwaway", "canonical_source": "https://dev.to/earlgreyhot1701d/block-zero-oh-no-claude-kiro-and-i-over-engineered-the-throwaway-5d42", "published_at": "2026-09-01 03:59:25+00:00", "updated_at": "2026-09-01 04:21:40.939659+00:00", "lang": "en", "topics": ["ai-agents", "developer-tools", "ai-products"], "entities": ["Porch Light", "Kiro", "Claude", "Bedrock AgentCore", "CloudWatch"], "alternates": {"html": "https://wpnews.pro/news/block-zero-oh-no-claude-kiro-and-i-over-engineered-the-throwaway", "markdown": "https://wpnews.pro/news/block-zero-oh-no-claude-kiro-and-i-over-engineered-the-throwaway.md", "text": "https://wpnews.pro/news/block-zero-oh-no-claude-kiro-and-i-over-engineered-the-throwaway.txt", "jsonld": "https://wpnews.pro/news/block-zero-oh-no-claude-kiro-and-i-over-engineered-the-throwaway.jsonld"}}