<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Hyun Sung Cho</title>
    <description>The latest articles on DEV Community by Hyun Sung Cho (@inversed).</description>
    <link>https://dev.to/inversed</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F846762%2Fd686efcd-d72a-42ca-b059-5fe900fd97cc.JPG</url>
      <title>DEV Community: Hyun Sung Cho</title>
      <link>https://dev.to/inversed</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/inversed"/>
    <language>en</language>
    <item>
      <title>Day 2: The Demo Worked in One Prompt. Then Replay Fell Apart.</title>
      <dc:creator>Hyun Sung Cho</dc:creator>
      <pubDate>Wed, 28 Oct 2026 21:44:31 +0000</pubDate>
      <link>https://dev.to/inversed/day-2-the-demo-worked-in-one-prompt-then-replay-fell-apart-44jp</link>
      <guid>https://dev.to/inversed/day-2-the-demo-worked-in-one-prompt-then-replay-fell-apart-44jp</guid>
      <description>&lt;p&gt;Yesterday I pivoted my shelved testing project into edge-pilot: let an agent drive a browser once, then replay that flow forever at zero LLM cost, with the captured API calls as the oracle. The Day 1 milestone was small on purpose — an MCP skeleton that can record and replay one real checkout end to end.&lt;/p&gt;

&lt;p&gt;Today I tried to build it. The demo worked immediately. Replaying it did not.&lt;/p&gt;

&lt;p&gt;What worked&lt;/p&gt;

&lt;p&gt;I stood up the MCP authoring server. An external agent (Claude Code, in my case) drives the browser through edge-pilot's tools — ep_navigate, ep_snapshot, ep_click, ep_fill, ep_save_scenario — and edge-pilot does the hardening behind each action.&lt;/p&gt;

&lt;p&gt;From one prompt, the agent walked our real shop: opened the treatments page, added an Aromatherapy Massage, filled in guest, therapist, date, and time, entered a test card, and completed checkout. A real order came back. I froze the verified run and replayed it with no model calls at all — it created the next orders (I ended the day with test orders #513950001 through #513950006). The "drive once, replay free" loop exists.&lt;/p&gt;

&lt;p&gt;Then I tried to make replay reliable, and every weak assumption fell out at once.&lt;/p&gt;

&lt;p&gt;What broke&lt;/p&gt;

&lt;p&gt;The recording was garbage. Replay kept failing because the recorder simply wasn't capturing every action the user took. There's no clever fix here — if the recording is lossy, nothing downstream can be trusted. My note to myself for the week:&lt;/p&gt;

&lt;p&gt;Recording must be perfect. It has to save every single one of the user's browser actions.&lt;/p&gt;

&lt;p&gt;The selector logic grabbed the wrong field. My old resolveTarget walked a fixed priority list — css → data-testid → name → aria → role → text — and judged each signal in isolation. On the real payment form (MUI), every signal was non-unique: three inputs shared #outlined-basic, there were no test IDs, everything was type=text. So it fell through to a shared CSS selector, .first() picked the wrong input, and a zip code (12342) got typed into the Address line. The order was rejected.&lt;/p&gt;

&lt;p&gt;A test that silently fills the wrong field is worse than no test at all.&lt;/p&gt;

&lt;p&gt;So I rebuilt element identity as a multi-signal fingerprint with a weighted scorer. Instead of trusting one signal, weak signals combine: role=textbox + a nearby label "Zip code" + nth-position-in-form can be uniquely identifying even when id, name, and type are all shared. If nothing clears a confidence threshold, edge-pilot refuses to guess and emits a testability warning ("add a data-testid here") instead of quietly doing the wrong thing. It's framework-agnostic — no data-testid required.&lt;/p&gt;

&lt;p&gt;The live site drifted under me. A time slot I kept booking went SOLD OUT from my own repeated test orders, so a recorded step stopped matching. A cart-page dropdown came back with a different id mid-run and broke its selector.&lt;/p&gt;

&lt;p&gt;Annoying — but also the entire reason edge-pilot exists. Selectable dates move, totals change, options disappear. This is the drift that makes me re-verify flows by hand every time. Watching it break my own replay on day two was oddly validating: this is the problem, reproduced.&lt;/p&gt;

&lt;p&gt;The oracle, wired in&lt;/p&gt;

&lt;p&gt;I also made the captured network calls into assertions on save. Replay no longer just checks that a button was clicked — it checks that POST /order returned 200 with an orderId in the body. "It didn't crash" is finally starting to mean "the order was actually created."&lt;/p&gt;

&lt;p&gt;Where it actually stands&lt;/p&gt;

&lt;p&gt;I did not hit the milestone. Record → replay of one full checkout still isn't reliable end to end — the recording gap is the blocker, and the fingerprint resolver and confidence threshold aren't fully wired into the replayer yet. Everything I built today is still uncommitted.&lt;/p&gt;

&lt;p&gt;And I'll be honest about the doubt I ended Day 1 with, because it got louder today, not quieter:&lt;/p&gt;

&lt;p&gt;If the product quality is worse than just prompting a plain LLM, who would use it?&lt;/p&gt;

&lt;p&gt;The bet is narrow and specific: zero-token deterministic replay + a real backend-state oracle is the thing a one-shot agent can't give you. Everything else is table stakes now. Today didn't prove the bet — it just made the gap I have to cross very concrete.&lt;/p&gt;

&lt;p&gt;Next: fix recording so it captures every action, then get one real checkout to replay green, end to end.&lt;/p&gt;

&lt;p&gt;If you record browser flows for testing, how do you keep your element targeting from silently matching the wrong thing? That's the part eating me right now.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>testing</category>
      <category>buildinpublic</category>
    </item>
    <item>
      <title>Day 1 Back: Someone Already Built the Thing I Was Stuck On, So I'm Pivoting</title>
      <dc:creator>Hyun Sung Cho</dc:creator>
      <pubDate>Tue, 27 Oct 2026 00:16:07 +0000</pubDate>
      <link>https://dev.to/inversed/day-1-back-someone-already-built-the-thing-i-was-stuck-on-so-im-pivoting-8hh</link>
      <guid>https://dev.to/inversed/day-1-back-someone-already-built-the-thing-i-was-stuck-on-so-im-pivoting-8hh</guid>
      <description>&lt;p&gt;I came back today from two months of paternity leave.&lt;/p&gt;

&lt;p&gt;My team switched to an AI-agent workflow about nine months ago. Agents plan, implement, review, test, and deploy, and I haven't written much code by hand in months. Not much changed while I was gone, but the AI tooling had moved on.&lt;/p&gt;

&lt;p&gt;This is the first post in a daily series about what I build, what breaks, and what being a developer means now.&lt;/p&gt;

&lt;h2&gt;
  
  
  What I did today
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Caught up on two months in an hour
&lt;/h3&gt;

&lt;p&gt;A Slack bot summarized the threads I'd missed, and I used Claude to dig through the commit history for the changes that actually mattered. Two months of context took about an hour.&lt;/p&gt;

&lt;h3&gt;
  
  
  Fixed a Node.js security issue
&lt;/h3&gt;

&lt;p&gt;Our security-scanning agent flagged a vulnerable Node.js patch version. I opened a shell into a production pod to check what was actually running, and it was the affected version.&lt;/p&gt;

&lt;p&gt;Our images used &lt;code&gt;node:22-alpine&lt;/code&gt; and our CI used &lt;code&gt;lts/*&lt;/code&gt;, so we had picked up the vulnerable patch without noticing. I had an agent pin every runtime Dockerfile and CI job to the same exact patched version:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;chore(deploy): pin node across runtime images and CI

- Dockerfile base images: node:22-alpine → node:22.x.y-alpine
- CI node-version: 22 / lts/* → 22.x.y
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I verified it on staging before release.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Lesson:&lt;/strong&gt; floating tags trade reproducibility for convenience. If prod, CI, and local can each resolve a different patch version, pin them.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  Debugged a state mismatch
&lt;/h3&gt;

&lt;p&gt;An order showed as active, but its linked appointment didn't. I asked an agent to analyze it, and its explanation didn't make sense to me, so I read the code myself.&lt;/p&gt;

&lt;p&gt;My current hypothesis is that two confirm requests raced each other. The first moved the appointment to active, and the second saw the state had already changed and skipped it. I still need to reproduce it before I'm sure.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Lesson:&lt;/strong&gt; agents are fast, but you still have to judge whether their answer is plausible.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  The moment that changed my plan
&lt;/h2&gt;

&lt;p&gt;For years, the most painful part of development for me has been UI testing.&lt;/p&gt;

&lt;p&gt;A single order goes through several pages. A guest's check-in-to-payment flow has a dozen variables. Unit and integration tests never fully reassured me, so I kept verifying by hand. I've created more fake orders than I can count.&lt;/p&gt;

&lt;p&gt;Before AI tools existed, I built Playwright and Puppeteer harnesses again and again. I kept wondering why small teams like mine don't get good UI testing tools, and why I couldn't just say &lt;em&gt;"here's the URL, go test it."&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;So I started building an AI-driven testing tool myself. I extracted DOM elements, sent them to an LLM, cleaned up the responses, and kept fighting to cut token usage. I burned out before it really worked and shelved it.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Today my mentor showed me an agent that drives a browser directly.&lt;/strong&gt; I gave it a prompt, and it placed a test order flawlessly.&lt;/p&gt;

&lt;p&gt;I was amazed and a little angry. Someone else had the same problem and solved it well. The base model was already good enough. I had spent my energy figuring out how to hand things to the LLM, when I should have let it do the work.&lt;/p&gt;

&lt;h2&gt;
  
  
  The pivot: edge-pilot
&lt;/h2&gt;

&lt;p&gt;A browser-driving agent is great at exploring a flow &lt;strong&gt;once&lt;/strong&gt;. But:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;every rerun costs tokens and needs a human to prompt it,&lt;/li&gt;
&lt;li&gt;the scripts it writes break when the UI changes,&lt;/li&gt;
&lt;li&gt;and "the script didn't crash" doesn't mean the order was actually created.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;So I'm turning my shelved project into &lt;strong&gt;edge-pilot&lt;/strong&gt;:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Record by prompt, once.&lt;/strong&gt; An agent drives the browser through edge-pilot's MCP tools (&lt;code&gt;navigate&lt;/code&gt;, &lt;code&gt;snapshot&lt;/code&gt;, &lt;code&gt;click&lt;/code&gt;, &lt;code&gt;fill&lt;/code&gt;, &lt;code&gt;save_scenario&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Capture what lasts.&lt;/strong&gt; Behind each action, edge-pilot replaces the snapshot's temporary ref with a durable, multi-signal element fingerprint and records the network effects.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Attach an oracle automatically.&lt;/strong&gt; On save, the captured API calls become assertions, for example &lt;code&gt;POST /order → 200&lt;/code&gt; with an &lt;code&gt;orderId&lt;/code&gt; in the response body.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Replay forever at zero LLM cost.&lt;/strong&gt; Deterministic replay locally or in CI, and an alert when the revenue path actually breaks, not when a button moves.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Later, when a redesign breaks a step, only that one step goes back to the LLM to be re-fingerprinted.&lt;/p&gt;

&lt;p&gt;The first milestone is small on purpose: an MCP server with navigate, snapshot, click, and fill, fingerprint capture, network capture, auto-assertions, and SQLite storage. If it can record and replay one real checkout flow end to end, the core idea works.&lt;/p&gt;

&lt;h2&gt;
  
  
  The harder question
&lt;/h2&gt;

&lt;p&gt;The rule I'm adopting: &lt;strong&gt;ship something that solves the problem, not something perfect.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;I also want to answer something I've avoided. Why do so many of my ideas stop at the idea stage? And what does a developer career look like when I'm no longer the one typing the code?&lt;/p&gt;

&lt;p&gt;I don't have answers yet. That's what this series is for.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Next:&lt;/strong&gt; get the edge-pilot MCP skeleton to record one real checkout flow.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;If you've fought the same UI-testing battle on a small team, I'd love to hear how you handle it.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>ai</category>
      <category>testing</category>
      <category>devops</category>
      <category>buildinpublic</category>
    </item>
  </channel>
</rss>
