<?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: Arun Kumar T</title>
    <description>The latest articles on DEV Community by Arun Kumar T (@arun_kumart_22e9a9959b10).</description>
    <link>https://dev.to/arun_kumart_22e9a9959b10</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%2F4188557%2F9cc5e530-e187-4cc7-a02e-38c393900cb9.png</url>
      <title>DEV Community: Arun Kumar T</title>
      <link>https://dev.to/arun_kumart_22e9a9959b10</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/arun_kumart_22e9a9959b10"/>
    <language>en</language>
    <item>
      <title>An AI agent can reverse-engineer your entire repo &amp; app in 10 minutes :) Thanks to REA, so I built the REAshield</title>
      <dc:creator>Arun Kumar T</dc:creator>
      <pubDate>Sun, 01 Nov 2026 03:19:19 +0000</pubDate>
      <link>https://dev.to/arun_kumart_22e9a9959b10/an-ai-agent-can-reverse-engineer-your-entire-repo-app-in-10-minutes-thanks-to-rea-so-i-built-451o</link>
      <guid>https://dev.to/arun_kumart_22e9a9959b10/an-ai-agent-can-reverse-engineer-your-entire-repo-app-in-10-minutes-thanks-to-rea-so-i-built-451o</guid>
      <description>&lt;p&gt;Right now, while you're reading this, your shipped app is defenseless.&lt;/p&gt;

&lt;p&gt;Not "theoretically." Not "if someone really tried." Today, anyone can point an AI&lt;br&gt;
agent at your bundle, walk away, and come back to a clean, plain-English teardown&lt;br&gt;
of exactly how your licensing works, where your pricing logic lives, and how to&lt;br&gt;
tear it out — with the code to do it.&lt;/p&gt;

&lt;p&gt;No cracking. No debugger. No late nights in devtools. The agent reads your files,&lt;br&gt;
rebuilds your entire app in its head, and hands the attacker the map.&lt;/p&gt;

&lt;p&gt;This isn't a warning about the future. The tools are live. So I built the thing&lt;br&gt;
that fights back, and it's open source. Here's how the attack works, why it's so&lt;br&gt;
devastating, and the exact moves that make it fall apart.&lt;/p&gt;
&lt;h2&gt;
  
  
  The attacker: a reverse-engineering machine that works for free
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://github.com/morluto/rea" rel="noopener noreferrer"&gt;REA&lt;/a&gt; hands a coding agent a full&lt;br&gt;
reverse-engineering toolbox over MCP. Aim it at your shipped &lt;code&gt;app.asar&lt;/code&gt; or bundle&lt;br&gt;
and — &lt;strong&gt;without ever running your app&lt;/strong&gt; — it statically reconstructs &lt;em&gt;everything&lt;/em&gt;:&lt;br&gt;
every module, import, route, IPC channel, and string. On a real ~14 MB Electron&lt;br&gt;
app that's a graph of roughly &lt;strong&gt;ten thousand nodes&lt;/strong&gt;. Then the agent reads a&lt;br&gt;
summary of that graph and answers, in English: &lt;em&gt;"here's how feature X works, and&lt;br&gt;
here's the code."&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Minutes. For free. At scale. On every app you've ever shipped.&lt;/p&gt;
&lt;h3&gt;
  
  
  And REA isn't alone
&lt;/h3&gt;

&lt;p&gt;REA is the sharpest example, but it's a &lt;em&gt;category&lt;/em&gt;, and the category is growing:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;&lt;a href="https://github.com/morluto/rea" rel="noopener noreferrer"&gt;REA&lt;/a&gt;&lt;/strong&gt; — an MCP server that gives a coding
agent a full reverse-engineering toolbox. Statically reconstructs an app's
whole module/IPC/route graph and lets the agent explain any feature from it.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;a href="https://github.com/jehna/humanify" rel="noopener noreferrer"&gt;humanify&lt;/a&gt;&lt;/strong&gt; — uses LLMs to &lt;em&gt;un-minify&lt;/em&gt;
JavaScript, handing readable, meaningful names back to your mangled code. Your
obfuscation's worst nightmare.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;a href="https://github.com/j4k0xb/webcrack" rel="noopener noreferrer"&gt;webcrack&lt;/a&gt;&lt;/strong&gt; /
&lt;strong&gt;&lt;a href="https://github.com/pionxzh/wakaru" rel="noopener noreferrer"&gt;wakaru&lt;/a&gt;&lt;/strong&gt; — unpack and unminify
webpack/bundled JS back toward the original, module-by-module source.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Wire any of these into an agent and the loop runs itself: unpack → rename →&lt;br&gt;
map → explain → clone. The barrier to reverse-engineering your app just dropped&lt;br&gt;
from "a skilled human with a weekend" to "a prompt."&lt;/p&gt;
&lt;h3&gt;
  
  
  What it eats
&lt;/h3&gt;

&lt;p&gt;Starve the attacker — but first, know the diet. It feeds on:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Your module graph&lt;/strong&gt; — the literal shape of every &lt;code&gt;import&lt;/code&gt; and &lt;code&gt;require&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Your names&lt;/strong&gt; — every identifier you shipped is a signpost.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Your strings&lt;/strong&gt; — routes, errors, keys, and IPC channel names.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Your source maps&lt;/strong&gt; — ship these and you didn't get reverse-engineered. You
published your source with a bow on it.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;
  
  
  Its fatal weakness — and your entire opening
&lt;/h3&gt;

&lt;p&gt;Here's what they don't tell you: this attacker is terrifying but &lt;strong&gt;narrow&lt;/strong&gt;, and&lt;br&gt;
it confesses its limits out loud.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;It is &lt;strong&gt;100% static&lt;/strong&gt;. It never runs your app. Anything that only exists at
runtime is &lt;strong&gt;invisible&lt;/strong&gt; to it.&lt;/li&gt;
&lt;li&gt;It &lt;strong&gt;will not guess&lt;/strong&gt;. A name assembled at runtime? It writes "unresolved" and
moves on. On a real test app, &lt;strong&gt;14 of ~22 IPC operations with computed names
were left blank.&lt;/strong&gt; Holes in the map.&lt;/li&gt;
&lt;li&gt;It &lt;strong&gt;buckles at scale&lt;/strong&gt;, dropping relationships when the graph gets big.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;So forget "make it unreadable." Obfuscation is a speed bump a machine rolls over.&lt;br&gt;
The real play: &lt;strong&gt;starve the static graph, and bury your crown jewels in the exact&lt;br&gt;
blind spots this attacker admits it cannot see.&lt;/strong&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  Obfuscation is paint, not armor
&lt;/h2&gt;

&lt;p&gt;Minify, mangle, encrypt your strings — sure. Just know it's the &lt;strong&gt;weakest,&lt;br&gt;
first-to-fall&lt;/strong&gt; layer in the stack. LLM-assisted deobfuscation improves every&lt;br&gt;
month, and even with garbage names, your entire structure is still sitting there&lt;br&gt;
for the graph builder to walk. Scrambling names doesn't hide the map.&lt;/p&gt;

&lt;p&gt;Real armor, ranked by how long it survives contact:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Don't ship the secret.&lt;/strong&gt; Move it off the device, period.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Get it off the JS graph.&lt;/strong&gt; WebAssembly. Bytecode.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Turn static into runtime.&lt;/strong&gt; Computed imports, computed channels, dispatch
tables — the blanks the agent can't fill.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Make every build different.&lt;/strong&gt; Version-diffing: dead on arrival.&lt;/li&gt;
&lt;li&gt;
&lt;em&gt;Then&lt;/em&gt; obfuscate and drown the rest in decoys.&lt;/li&gt;
&lt;/ol&gt;
&lt;h2&gt;
  
  
  The shield
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://github.com/HMAKT99/reashield" rel="noopener noreferrer"&gt;REAShield&lt;/a&gt; is an open-source, drop-in npm&lt;br&gt;
dev-dependency that turns every move above into one config and one command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// shield.config.cjs&lt;/span&gt;
&lt;span class="nx"&gt;module&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;exports&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;input&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;src/index.js&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;output&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;dist-shielded&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;preset&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;balanced&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;protect&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;licenseCheck&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;mode&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;relocate&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="c1"&gt;// rip the real body off-device&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;sealedCalc&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;   &lt;span class="na"&gt;mode&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;seal&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;      &lt;span class="c1"&gt;// ship it as ciphertext&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;pricingLogic&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;mode&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;wasm&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;      &lt;span class="c1"&gt;// compile it to WebAssembly&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;featureGate&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;  &lt;span class="na"&gt;mode&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;obfuscate&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="c1"&gt;// harden it in place&lt;/span&gt;
  &lt;span class="p"&gt;],&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npx reashield build     &lt;span class="c"&gt;# hardened client + a server skeleton&lt;/span&gt;
npx reashield &lt;span class="nb"&gt;test&lt;/span&gt;      &lt;span class="c"&gt;# measures what the attacker can STILL see&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;What each mode does to the agent:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Relocate&lt;/strong&gt; — the function's real body is lifted out of your app and into a
generated server handler. The client keeps one opaque remote-call stub. &lt;strong&gt;You
cannot graph code that was never shipped.&lt;/strong&gt; This move never stops working —
it's the oldest rule in security, enforced automatically.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Seal&lt;/strong&gt; — the module ships as ciphertext, decrypted at runtime with a
server-fetched key. Static analysis gets a wall of bytes.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;WASM&lt;/strong&gt; — numeric hot-paths compile to a real WebAssembly module (binary,
synchronous, behavior untouched). Erased from the JS graph entirely.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Starvation&lt;/strong&gt; (always on) — one flat module, no source maps, encrypted
strings, and literal IPC/route names rewritten into runtime-computed ones: the
exact names the agent surrenders on.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Polymorphism + decoys&lt;/strong&gt; — every build is restructured and renamed so releases
can't be diffed, and the graph is flooded with inert fake "feature" clusters so
the agent's summary trips over false leads first.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Don't trust it — prove it
&lt;/h2&gt;

&lt;p&gt;This is the part I refuse to hand-wave. REAShield runs &lt;strong&gt;the actual attacker&lt;br&gt;
(REA) against your own before/after build&lt;/strong&gt; and shows you what changed.&lt;/p&gt;

&lt;p&gt;On the bundled example — a small library with a license check, pricing logic, and&lt;br&gt;
a sealed scoring function:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Secret strings and protected identifiers left in the shipped client: &lt;strong&gt;6 → 0.&lt;/strong&gt;
The real algorithm and its constants now live only on the server.&lt;/li&gt;
&lt;li&gt;String literals surviving verbatim into the output: &lt;strong&gt;100% → 0%.&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;The import graph: &lt;strong&gt;collapsed to a single module.&lt;/strong&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Run &lt;code&gt;npx reashield test --rea&lt;/code&gt; against your own app for REA's own "modules&lt;br&gt;
resolved / relationships resolved" counts, before vs after — and on a real&lt;br&gt;
multi-thousand-node app, that drop is brutal.&lt;/p&gt;

&lt;p&gt;Because REA ships constantly, the harness doubles as a &lt;strong&gt;CI gate pinned across&lt;br&gt;
REA versions&lt;/strong&gt;: a new REA that recovers more than your committed baseline &lt;strong&gt;fails&lt;br&gt;
the build.&lt;/strong&gt; Protection stops being a hope and becomes a test.&lt;/p&gt;

&lt;h2&gt;
  
  
  The honest part — the line that makes the rest credible
&lt;/h2&gt;

&lt;p&gt;I'll say the thing straight, because overclaiming is how security tools die:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Nothing that runs on someone else's machine is truly unreversible. REAShield&lt;br&gt;
doesn't claim to be — and neither should you.&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;What it &lt;em&gt;actually&lt;/em&gt; delivers: it turns a 10-minute automated agent job into&lt;br&gt;
&lt;strong&gt;days&lt;/strong&gt; of specialist human grind, and kills &lt;strong&gt;most&lt;/strong&gt; automated attacks at the&lt;br&gt;
door. A determined human with time still gets through. Relocation and sealing need&lt;br&gt;
a backend you secure, and the request/response boundary stays observable. It's&lt;br&gt;
behavior-preserving, transparent (no phone-home), and strictly defensive — it&lt;br&gt;
protects code &lt;strong&gt;you&lt;/strong&gt; own and ship. Never a weapon against anyone else's.&lt;/p&gt;

&lt;p&gt;One line to walk away with: &lt;strong&gt;the strongest defense isn't a tool, it's a&lt;br&gt;
decision. Whatever must truly stay secret belongs on your server — where no&lt;br&gt;
bundle, and no agent, can ever reach it.&lt;/strong&gt;&lt;/p&gt;




&lt;p&gt;Repo + docs: &lt;strong&gt;&lt;a href="https://github.com/HMAKT99/reashield" rel="noopener noreferrer"&gt;https://github.com/HMAKT99/reashield&lt;/a&gt;&lt;/strong&gt; — &lt;code&gt;npm i -D reashield&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Do reverse engineering? Come break the relocation and decoy seams and tell me&lt;br&gt;
where they're weakest. I want the teardown.&lt;/p&gt;

</description>
      <category>agents</category>
      <category>security</category>
      <category>electron</category>
      <category>node</category>
    </item>
    <item>
      <title>Your AI agent writes Playwright tests that pass while your API returns 500</title>
      <dc:creator>Arun Kumar T</dc:creator>
      <pubDate>Sun, 01 Nov 2026 03:08:58 +0000</pubDate>
      <link>https://dev.to/arun_kumart_22e9a9959b10/your-ai-agent-writes-playwright-tests-that-pass-while-your-api-returns-500-1p0d</link>
      <guid>https://dev.to/arun_kumart_22e9a9959b10/your-ai-agent-writes-playwright-tests-that-pass-while-your-api-returns-500-1p0d</guid>
      <description>&lt;p&gt;AI agents now write a lot of Playwright tests. You ask Claude Code or Copilot to "add a test for the checkout", or let an agent explore your app through Playwright MCP and turn what it did into a spec. Healer agents even fix failing tests for you.&lt;/p&gt;

&lt;p&gt;Here is the kind of test they write:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;test&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;expect&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;@playwright/test&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="nf"&gt;test&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;places an order&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;page&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;page&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;goto&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;/&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;page&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getByLabel&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Name&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;fill&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Ada&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;page&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getByRole&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;button&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Place order&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;}).&lt;/span&gt;&lt;span class="nf"&gt;click&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;page&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getByRole&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;status&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)).&lt;/span&gt;&lt;span class="nf"&gt;toContainText&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Order placed&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It's a good test: role-based locators and a web-first assertion. It passes.&lt;/p&gt;

&lt;p&gt;It also passes when the order API returns &lt;strong&gt;500 and stores nothing&lt;/strong&gt;, as long as the page still shows "Order placed". The agent checked what it could &lt;em&gt;see&lt;/em&gt;. Nobody told it to check what the server did, and agents almost never add a network assertion on their own.&lt;/p&gt;

&lt;p&gt;That matters more with agents than with people. A human who wrote the checkout code might remember the API can fail. An agent generating fifty tests from what's on screen won't, and a healer agent that "fixes" a red test by updating the expected text can make things worse. The suite goes green while the backend is broken.&lt;/p&gt;

&lt;h2&gt;
  
  
  The one-line fix
&lt;/h2&gt;

&lt;p&gt;Change the import, in the tests the agent wrote or in the template it writes from:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;test&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;expect&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;@vedhajs/playwright-test&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Nothing else changes. Same test, same broken app:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fmy0xvny81iifz8mxfmup.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fmy0xvny81iifz8mxfmup.gif" alt="The same Playwright test with two imports: @playwright/test passes, @vedhajs/playwright-test fails with &amp;quot;POST /api/orders returned 500&amp;quot;" width="800" height="303"&gt;&lt;/a&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;  ✓  1 1-playwright.spec.ts › places an order (import from @playwright/test)
  ✘  2 2-vedha.spec.ts › places an order (import from @vedhajs/playwright-test)

    Error: Vedha guard: the test's own checks passed, but the app reported a problem:
      - POST /api/orders returned 500
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;On a healthy app, both pass.&lt;/p&gt;

&lt;p&gt;The failure message is also written for whoever reads it next, human or agent: what the app did, and how to accept it if it was expected. A healer agent gets a real reason instead of a green run.&lt;/p&gt;

&lt;h2&gt;
  
  
  What it checks
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;@vedhajs/playwright-test&lt;/code&gt; re-exports Playwright's &lt;code&gt;test&lt;/code&gt; and &lt;code&gt;expect&lt;/code&gt; with an automatic fixture ("guard mode") that watches the browser context while each test runs:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Fails the test:&lt;/strong&gt; any &lt;strong&gt;5xx&lt;/strong&gt; from your app's own site, or a &lt;strong&gt;write request&lt;/strong&gt; (POST/PUT/PATCH/DELETE) that failed outright, even when every &lt;code&gt;expect&lt;/code&gt; passed.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Warns, without failing:&lt;/strong&gt; a &lt;strong&gt;4xx answer to a write&lt;/strong&gt;, and &lt;strong&gt;uncaught page errors&lt;/strong&gt;. Validation tests expect a 422 and third-party scripts throw, so these become annotations in the report instead of failures.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Ignores:&lt;/strong&gt; requests to other sites (analytics, CDNs).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Attaches:&lt;/strong&gt; the findings to the test result as &lt;code&gt;vedha-guard.json&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;When a finding is expected, opt out per test or per endpoint:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="nx"&gt;test&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;use&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;vedhaGuard&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;strict&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt; &lt;span class="c1"&gt;// 4xx writes and page errors fail too&lt;/span&gt;
&lt;span class="nx"&gt;test&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;use&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;vedhaGuard&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;ignore&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;/api/flaky&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sr"&gt;/&lt;/span&gt;&lt;span class="se"&gt;\/&lt;/span&gt;&lt;span class="sr"&gt;v2&lt;/span&gt;&lt;span class="se"&gt;\/&lt;/span&gt;&lt;span class="sr"&gt;/&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="na"&gt;hosts&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;api.other-domain.com&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="nx"&gt;test&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;use&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;vedhaGuard&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt; &lt;span class="c1"&gt;// off, for a test that expects a 500&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It is still Playwright's runner, so retries, sharding, reporters and traces work as before.&lt;/p&gt;

&lt;h2&gt;
  
  
  Making agents use it
&lt;/h2&gt;

&lt;p&gt;Put it where the agent will pick it up:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Your project instructions&lt;/strong&gt; (&lt;code&gt;CLAUDE.md&lt;/code&gt;, &lt;code&gt;AGENTS.md&lt;/code&gt;, Copilot instructions): "Import &lt;code&gt;test&lt;/code&gt; and &lt;code&gt;expect&lt;/code&gt; from &lt;code&gt;@vedhajs/playwright-test&lt;/code&gt;, not &lt;code&gt;@playwright/test&lt;/code&gt;."&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Existing specs:&lt;/strong&gt; agents copy the patterns they find, so once your specs use the import, new ones tend to follow.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;A lint rule&lt;/strong&gt; that bans importing from &lt;code&gt;@playwright/test&lt;/code&gt; in spec files, if you want to enforce it.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  When the agent drives the browser itself
&lt;/h2&gt;

&lt;p&gt;Guard mode is for the tests an agent writes. When the agent &lt;em&gt;is&lt;/em&gt; the tester, driving the browser live and reporting pass or fail, Vedha also ships an MCP server that checks every step the same way. In a small pilot on held-out tasks (one model, 3 trials per task), the agent missed &lt;strong&gt;9&lt;/strong&gt; seeded bugs with Vedha's MCP server against &lt;strong&gt;26&lt;/strong&gt; with Playwright MCP. That's a separate setup from guard mode, covered in &lt;a href="https://dev.to/arun_kumart_22e9a9959b10/is-playwright-alone-enough-for-agentic-testing-433p"&gt;an earlier post&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Limits
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;A hand-written &lt;code&gt;waitForResponse&lt;/code&gt; assertion catches this too. Guard mode is the safety net for the many tests, agent-written or not, that don't have one.&lt;/li&gt;
&lt;li&gt;In Vedha's benchmark, tests with typical text and URL checks caught &lt;strong&gt;0 of 140&lt;/strong&gt; seeded defects with plain Playwright, and &lt;strong&gt;60 of 140&lt;/strong&gt; with Vedha's page-health check: every defect where the server rejected or failed the write. Guard mode applies the same rules to whole tests, but it hasn't been benchmarked separately yet.&lt;/li&gt;
&lt;li&gt;It does not catch a write that returns 200 but stores nothing or stores the wrong value. Vedha's checked steps can read the data back, but that's opt-in and needs more than one line.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Try it
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;-D&lt;/span&gt; @vedhajs/playwright-test
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Change the import in one agent-written spec and run it. If a test that used to pass now fails, look at the request it names. Either the agent's test was hiding a bug, or it's an expected error to add to &lt;code&gt;ignore&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Repo, demo and benchmark data: &lt;strong&gt;&lt;a href="https://github.com/HMAKT99/VEDHA" rel="noopener noreferrer"&gt;https://github.com/HMAKT99/VEDHA&lt;/a&gt;&lt;/strong&gt; (Apache-2.0)&lt;/p&gt;

&lt;p&gt;I'd like to hear what it finds in agent-written suites, and about any false alarm.&lt;/p&gt;

</description>
      <category>playwright</category>
      <category>testing</category>
      <category>ai</category>
      <category>agents</category>
    </item>
    <item>
      <title>Is Playwright alone enough for agentic testing?</title>
      <dc:creator>Arun Kumar T</dc:creator>
      <pubDate>Sat, 31 Oct 2026 13:01:00 +0000</pubDate>
      <link>https://dev.to/arun_kumart_22e9a9959b10/is-playwright-alone-enough-for-agentic-testing-433p</link>
      <guid>https://dev.to/arun_kumart_22e9a9959b10/is-playwright-alone-enough-for-agentic-testing-433p</guid>
      <description>&lt;p&gt;More teams now let an AI agent test their web app: "test the checkout", "check the signup flow". The agent drives a browser through Playwright, clicks through the flow, and reports back: &lt;strong&gt;all tests passed&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;The problem is how the agent decides that. It looks at the page. If the page shows the success message it expected, the test passes. But a page can show success while the app is broken underneath: the API returned a 500, the server rejected the request, or it stored nothing at all. The test passes, and the bug ships.&lt;/p&gt;

&lt;p&gt;I wanted to measure how often that happens, and whether a testing layer could catch these bugs without the agent (or a human tester) writing extra assertions. The result is &lt;strong&gt;Vedha&lt;/strong&gt;, an open-source testing framework and MCP server built on Playwright.&lt;/p&gt;

&lt;h2&gt;
  
  
  A broken feature that passes its test
&lt;/h2&gt;

&lt;p&gt;Here is an order form with a seeded bug: the order API returns 500 and stores nothing, but the page still shows "Order placed". The same test, with the same check (wait for "Order placed"), is run twice:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fumc4t894nlkgub2bzmfg.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fumc4t894nlkgub2bzmfg.gif" alt="Playwright passes, Vedha fails the step on a silent 500, and the server stored 0 orders" width="800" height="185"&gt;&lt;/a&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Playwright  PASS   "Order placed" is on the page
Vedha       FAILED declared checks passed, but the page reported: POST /api/orders returned 500
Server      0 orders stored
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can run it yourself in about 3 seconds: &lt;code&gt;npx tsx examples/demo/run.ts&lt;/code&gt; in the repo.&lt;/p&gt;

&lt;p&gt;A careful tester would catch this in Playwright too, by asserting on the network response. Most tests don't, and agents almost never do.&lt;/p&gt;

&lt;h2&gt;
  
  
  What Vedha adds to Playwright
&lt;/h2&gt;

&lt;p&gt;Vedha keeps what Playwright does best (auto-waiting, locators, the browser itself) and adds a verification layer to every test step:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Every step gets a result:&lt;/strong&gt; &lt;code&gt;verified&lt;/code&gt;, &lt;code&gt;failed&lt;/code&gt;, &lt;code&gt;outcome_unknown&lt;/code&gt;, &lt;code&gt;unverified&lt;/code&gt; or &lt;code&gt;blocked&lt;/code&gt;. Never a silent pass.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Actions that change data are checked.&lt;/strong&gt; Mark a step as &lt;code&gt;mutating&lt;/code&gt; and Vedha watches the requests it sent. A 5xx, a rejected request or a page error fails the step even when the on-screen check passed. Where the API follows REST conventions, it also reads the data back to confirm it was stored.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;No duplicate side effects from retries.&lt;/strong&gt; If a click times out mid-submit, Vedha won't click "Place order" again and create a second order. It reports &lt;code&gt;outcome_unknown&lt;/code&gt; until a read-only check settles it.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Agent explorations become regression tests.&lt;/strong&gt; A verified flow can be exported as a plain &lt;code&gt;@playwright/test&lt;/code&gt; spec for CI.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Safe defaults for agents.&lt;/strong&gt; The MCP server won't start without a domain allowlist, treats page text as untrusted data, and redacts secrets you pass to it.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  The numbers, and their limits
&lt;/h2&gt;

&lt;p&gt;Every number comes from raw trial files in the repo, and each held-out test set was written before any run on it.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;AI agent testing&lt;/strong&gt; (Playwright MCP vs Vedha MCP, same model, same held-out test tasks):&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;/th&gt;
&lt;th&gt;Playwright MCP&lt;/th&gt;
&lt;th&gt;Vedha MCP&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Seeded bugs missed (sets 2-4)&lt;/td&gt;
&lt;td&gt;26&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;9&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Healthy flows passed (set 4)&lt;/td&gt;
&lt;td&gt;18/18&lt;/td&gt;
&lt;td&gt;17/18&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Median tokens, healthy flows (set 4)&lt;/td&gt;
&lt;td&gt;76,018&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;52,990 (-30%)&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Median wall time, healthy flows (set 4)&lt;/td&gt;
&lt;td&gt;169 s&lt;/td&gt;
&lt;td&gt;176 s (+4%)&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;Scripted tests, no model:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;With typical text/URL-only checks, Vedha caught &lt;strong&gt;60 of 140&lt;/strong&gt; seeded bugs; every Playwright and Selenium baseline caught 0.&lt;/li&gt;
&lt;li&gt;A 1,120-trial audit after the last change had &lt;strong&gt;0 false passes and 0 false fails&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;Median overhead: &lt;strong&gt;1.05x&lt;/strong&gt; hand-written Playwright.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;The limits:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The AI-agent results come from one free model, at 3 trials per task. That's a pilot, not a verdict.&lt;/li&gt;
&lt;li&gt;When an expert writes every check by hand, Vedha and Playwright &lt;strong&gt;tie&lt;/strong&gt;. Vedha's lead is with typical checks and with agents.&lt;/li&gt;
&lt;li&gt;Read-back needs a REST-style read endpoint: the same path, or its singular/plural sibling. GraphQL, separate read endpoints and filtered or per-user collections aren't covered.&lt;/li&gt;
&lt;li&gt;Vedha passed one fewer healthy flow than Playwright MCP on set 4, and it uses more tool calls.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Try it
&lt;/h2&gt;

&lt;p&gt;With Claude Code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;claude mcp add vedha &lt;span class="nt"&gt;--&lt;/span&gt; npx &lt;span class="nt"&gt;-y&lt;/span&gt; @vedhajs/mcp &lt;span class="nt"&gt;--allow-domain&lt;/span&gt; localhost
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then ask: "test the checkout flow on localhost:3000".&lt;/p&gt;

&lt;p&gt;Any MCP client takes the same command (&lt;code&gt;npx -y @vedhajs/mcp --allow-domain localhost&lt;/code&gt;). There is also an agent skill (&lt;code&gt;npx skills add HMAKT99/VEDHA&lt;/code&gt;), a CLI for scripted tests (&lt;code&gt;npm i -D @vedhajs/cli&lt;/code&gt;), and an SDK that wraps an existing Playwright &lt;code&gt;page&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Repo, benchmarks and raw data: &lt;strong&gt;&lt;a href="https://github.com/HMAKT99/VEDHA" rel="noopener noreferrer"&gt;https://github.com/HMAKT99/VEDHA&lt;/a&gt;&lt;/strong&gt; (Apache-2.0)&lt;/p&gt;

&lt;p&gt;I'd most like to hear about real apps where it gets things wrong: a false failure on a healthy flow, or a bug it should have caught.&lt;/p&gt;

</description>
      <category>testing</category>
      <category>playwright</category>
      <category>mcp</category>
      <category>ai</category>
    </item>
  </channel>
</rss>
