ITEM-6807 landed on my queue with three small bugs against the Create Event dialog for tournament scheduling. A file upload that broke on mobile. A competition-name field that cleared its own value on submit. A date placeholder that had not been updated since the form was built. I opened a session to fix those inputs. The inputs were not the problem.
HomeTeamsONLINE is a 25-year-old ASP-classic application. Modal dialogs were a reasonable choice when the app was built, and a load-bearing assumption by the time I inherited it. The Create Event dialog was one of hundreds of those patterns layered in over the years, each one reasonable at the time it was added, each one adding constraints the next builder had to work around. By the time I sat down with ITEM-6807, the dialog had accumulated fields across multiple tournament types and had become a surface where fixing one thing reliably broke another.
the dialog was the wrong container
The main session eventually logged 716 prompts. Somewhere in the middle of that, David, our designer, joined for a design review. He looked at the current state of the modal, asked a question I had not thought to ask, and the answer changed the direction of the day.
The question was: why is this a dialog at all?
Tournament creation is not a quick action. It has file uploads, a date range, a competition name, an organizer list, and mobile users who need a readable layout at every step. Dialogs are for confirmations and short inputs. Squeezing tournament creation into a modal was a legacy holdover, not a product decision. Every special case I was adding was a symptom of the wrong container, not an isolated bug.
The fix was to route “add new event” to a dedicated full-page form with ?action=create in the URL. The dialog was dropped and the page got the full layout it needed. Most of the bugs on the modal evaporated because the page had room for the inputs. This is not a new insight in web development. It still took a human in the room to see it. I had spent 716 prompts improving a form that needed to be a page.
what the design review actually killed
David made five concrete decisions in that session, each one resolving something I had been treating as a separate problem.
He renamed Organizers to Staff. That seems small. “Organizer” is internal jargon for a role concept that staff users do not think of themselves through. “Staff” is what they call themselves, and the rename reduced the label’s friction without changing anything else.
He moved the image upload action out of the main input flow and gave it a cleaner position on the page. On the dialog version, the upload was competing for space with every other input. On the full page, it sits where it belongs.
He adjusted section header and input label typography so the hierarchy was readable without squinting. The dialog had compressed everything to fit the modal width. The page version did not have to.
He restructured the overall layout so the form communicated intent rather than just enumerating fields. That is a different thing even if the fields are identical.
And he killed the dialog itself. That sounds obvious now. It had not been obvious during the session. It took someone outside the implementation to see that the container was the constraint.
the fixes that needed a real page
Once the form was a page, several things that had been hard became straightforward.
The competition-name field had been clearing on submit because of how the dialog’s state was wired. On the page form, the value is preserved through the action cycle, and that fix came from changing the container, not from patching the field.
The image upload had a MapPath issue where the temp copy was written to a path that did not survive the form submission round-trip. The fix was two lines: changing how the temp path was constructed so the next handler could reach it. On the dialog, that lifecycle had been invisible because the modal layer compressed the whole two-step into one apparent action. On the page, the steps were visible and the bug was easy to find.
Mobile layout had been wrapping inputs into columns that made the form unreadable on anything narrower than 800px. The page handled wrapping correctly because it was not constrained by dialog width.
Date placeholders were showing a format string instead of hint text on several browsers. That is a one-line fix once the input is visible and testable in isolation, but on the dialog it had been masked by the surrounding chrome. Input sizing and label alignment got a cleanup pass. Nothing individually significant, but the cumulative effect is a form that reads as intentional rather than accumulated.
For each of these, Claude handled the fix. Describe the broken behavior, get a working implementation back, review it. What Claude could not do, across 716 prompts in the main session and another 315 in the afternoon pass, was surface that the dialog itself was wrong. That required David.
AI_TEMP_ROOT and where the artifacts go
One operational side-lesson from the day. Screenshots, plans, and session artifacts had been landing in ad-hoc locations around the repo, some in tracked directories, some not. By the end of the session I had defined AI_TEMP_ROOT as a named constant pointing at a scratch location outside the tracked tree. Future sessions write their temp output there.
Small convention. Sessions on a 25-year-old codebase accumulate a lot of intermediate state, and without a named home for it, that state becomes noise you clean by hand or leave to pollute the repo history.
what the agent can and can’t do
Claude’s failure mode on ITEM-6807 was not a bug in the implementation. Everything it produced was correct. The competition-name fix was right. The MapPath temp-copy fix was right. The mobile layout pass was right.
An agent working inside a dialog will improve the dialog. It will keep iterating, tightening inputs, fixing edge cases, handling mobile breakpoints, getting the form closer to correct inside the wrong container. It will not spontaneously decide the container is the problem, dissolve the abstraction, and redirect the feature to a full page. That decision requires someone who can hold the user’s experience in mind alongside the code, who can ask “why is this a dialog at all” and mean it as a product question rather than a technical one.
In this case that was David. The ?action=create route exists because he asked the question. The rename from Organizers to Staff happened because he knew what staff actually call themselves. These are product decisions, not implementation decisions, and they only become visible once someone with product judgment enters the room.
Agents accelerate implementation. They do not replace the moment when a collaborator looks at the frame and says the frame is wrong. That gap is where most of the quality lives.