When you build software with a coding agent, the most important question isn't "does it work?" but "who checked it, and on what?". An iPhone emulator is not an iPhone: it can report that a page works while it's broken on the real phone. We saw it happen on the Sweet Pal website, and since then, for certain bugs, testing on a real device is the first step, not the last.
On the sweetpal.ai home page there's a section we call the stage. As you scroll, the picture of the iPhone stays pinned under the header while the app's screens change one after another, along with the text beside them. Technically it's a block with position: sticky inside a container a few screens tall, plus a little JavaScript that picks the screen based on how far you've scrolled. On a computer, it worked. Then one evening the message nobody wants to read arrived: "the parallax doesn't work on mobile". On the real phone, the drawn iPhone scrolled away with the rest of the page instead of staying pinned.
We asked the agent to find the cause, and its work was methodical. The site wouldn't run locally with real data, so it tested directly on sweetpal.ai with an automated browser emulating an iPhone. First with Chromium, Chrome's engine: the stage pinned. Then with WebKit, Safari's engine, to get closer to the real phone: it pinned there too. Then with screenshots, to look at what was actually on screen rather than just at numbers: the screens advanced one after another. One doubt remained, because for convenience it was skipping the cookie consent wall by setting the choice in advance, and that wall affects page scrolling; so it ran the test again through the wall, clicking the button as a person would. Same result. At that point the easy conclusion would have been "I can't reproduce it, it works in my environment". The emulator had given the same answer four times, and it was wrong four times.
When you can't reproduce it, reason from known causes
The right move was to change method. If a bug won't show itself, you stop hunting it by trying and start hunting it by reading: you walk up the chain of the stage's containers, one by one, looking for something known to break position: sticky on Safari for iPhone. There was exactly one thing out of place, in the global stylesheet shared with the technical documentation:
body { overflow-x: hidden; }
It had been put there for the documentation, and nobody on the website side was thinking about it anymore. It's a known cause: an ancestor with an overflow other than visible becomes the scrolling container that sticky elements refer to, and on Safari iOS that alone is enough for sticky to stop pinning where you expect. The site didn't even need it: its main container already trims anything that overflows with overflow-x: clip, which, unlike hidden, doesn't create a scrolling container. The fix was one line scoped to the website's pages, body:has(.sp-site) { overflow-x: visible; }, and the documentation stayed as it was. The agent also checked the opposite risk, that with overflow no longer hidden a page 320 pixels wide might start scrolling sideways: home, the English version, the three landing pages, contact and privacy, no horizontal scrolling.
The part we care about most is how it reported the result. It didn't write "fixed". It wrote that the fix was still to be verified, because the problem didn't reproduce in emulation, so it couldn't confirm it had removed it; on a real iPhone page scrolling is driven by the operating system, while the emulator simulates it inside a browser on a computer. And it didn't publish on its own, because on the site a push to the main branch reaches production within minutes. It asked for a test on a real iPhone and, if that wasn't enough, a description of exactly what was on screen: does the phone scroll away, or does it stay put while the screens don't change? And in which browser? Those are two different bugs, with two different causes. The answer was "publish it and I'll check". Commit, site rebuild, and one tip before testing: do a hard reload, because Safari might still serve the old stylesheet and make a correct fix look useless. A little later: "it worked".
What we learned
The bug itself was trivial, one line of CSS. The lessons weren't. Emulation emulates the engine, not the device: for scrolling, sticky elements and anything that depends on how the system handles a finger on the screen, "it works" only means "it works in emulation". If the bug won't reproduce, trying again in the same environment only produces more wrong confirmations; for Safari iOS the known causes of a sticky element that won't pin are few and documented, and you check them all by walking up the containers.
An unverified result is reported as unverified: "I applied a fix, but it still needs checking" is worth more than an optimistic "fixed", because it says where the uncertainty lies and who can remove it. Often that's the person, because they hold the real device: when working with an agent the cheapest check is picking up the phone, and it pays to ask for it right away, with a precise question, rather than after an hour of attempts. Fixes stay small, with the opposite risk checked, so that a wrong one is easy to take out. And what you learned gets written down: the agent noted in its project memory that emulation isn't enough for this kind of bug and that next time it should start from the known Safari iOS causes. A lesson that only lives in the conversation is lost by the next session.
In short:
- An iPhone emulator, even with Safari's engine, can say "it works" for scrolling and sticky bugs that are there on the real phone.
- The cause was
body { overflow-x: hidden }, known to breakposition: stickyon Safari iOS; the fix was one line scoped to the site. - When a bug won't reproduce, look for known causes instead of repeating tests in the same environment.
- Unverified work is reported as "to be verified", with a precise question for whoever holds the device.
- Lessons go where the next session will find them.