<?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: Wayne Ma</title>
    <description>The latest articles on DEV Community by Wayne Ma (@sacravenger).</description>
    <link>https://dev.to/sacravenger</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%2F3852772%2Fdf1bb805-4b40-4412-98ac-dca6a4e2f2f6.png</url>
      <title>DEV Community: Wayne Ma</title>
      <link>https://dev.to/sacravenger</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/sacravenger"/>
    <language>en</language>
    <item>
      <title>Building Mythcastera with Blender Truth and Saccade</title>
      <dc:creator>Wayne Ma</dc:creator>
      <pubDate>Wed, 16 Sep 2026 16:03:04 +0000</pubDate>
      <link>https://dev.to/sacravenger/building-mythcastera-with-blender-truth-and-saccade-3jgg</link>
      <guid>https://dev.to/sacravenger/building-mythcastera-with-blender-truth-and-saccade-3jgg</guid>
      <description>&lt;p&gt;We started Mythcastera with a simple wish: a fantasy town where AI residents have things to do. An inn to run, supplies to gather, a place to sit, someone to talk to. Goblins, pigfolk, and creatures outside town belong in that world. We want their choices to have visible consequences.&lt;/p&gt;

&lt;p&gt;Then we spent rather a lot of time staring at a goblin's shirt.&lt;/p&gt;

&lt;p&gt;That detour has been useful. Before a resident can convincingly live in a town, we need to get a character into the scene, give it an action, and see what actually happens when it moves. This update is about that work, and the small town taking shape around it.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F442ywitnkf9amqld2oit.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F442ywitnkf9amqld2oit.png" alt="The current Mythcastera town, with its inn, workshop and garden" width="800" height="506"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/nanlogic/saccade/blob/main/docs/showcase/2026-09-16/media/town-tour.mp4" rel="noopener noreferrer"&gt;Watch the 20-second town tour&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The scene now has an inn, a workshop, a strawberry patch, and the smaller things that make those places readable: baskets, crates, fences, and stacks of wood. We built and arranged the town assets through our Blender workflow. Mududu is the innkeeper; Kakka is the repairer. Their character definitions keep their appearance, background, and starting possessions separate from the animation files.&lt;/p&gt;

&lt;p&gt;We're experimenting with resident behavior too, including walking to places, sitting, conversation, and gathering. Some household activities still use placeholder motion. The longer-term aim is a town whose residents can keep themselves occupied; this is still a development preview.&lt;/p&gt;

&lt;h2&gt;
  
  
  Starting with a body that already works
&lt;/h2&gt;

&lt;p&gt;Our characters began with a purchased, licensed library of rigged models. That gave us a useful starting point: an existing skeleton, skin weights, and native animation. We kept the shared 44-bone rig while making character variations and clothes in Blender.&lt;/p&gt;

&lt;p&gt;The walking and running in these character studies originally came from that Blender asset. The fantasy clothing, species variations, and character-specific work are additions to that base. Keeping that distinction clear also helps us debug: we can compare a changed character with the original instead of guessing which part of the pipeline introduced a problem.&lt;/p&gt;

&lt;p&gt;Mududu now uses a separate head-and-neck module on the shared rig. The earlier rough-cloth goblin remains useful for comparison, but it isn't the current Mududu asset.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fysvq4bkvlonu771sd8v3.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fysvq4bkvlonu771sd8v3.png" alt="Mududu walking in the character preview" width="800" height="448"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F7sgbocfcwy8g0o2m94n4.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F7sgbocfcwy8g0o2m94n4.png" alt="Mududu resting on a bench outside the inn" width="800" height="506"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fsatveth19gc96k56r12a.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fsatveth19gc96k56r12a.png" alt="Human, goblin and pigfolk using the shared rig" width="800" height="238"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/nanlogic/saccade/blob/main/docs/showcase/2026-09-16/media/mythcastera-residents.mp4" rel="noopener noreferrer"&gt;Watch the 15-second character reel&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;These clips are manually staged motion demonstrations, not a demonstration of autonomous resident behavior.&lt;/p&gt;

&lt;h2&gt;
  
  
  Getting a swing into the browser
&lt;/h2&gt;

&lt;p&gt;For additional actions, we've been using Mixamo. Our upload candidate contains a skinned human mesh and its armature, exported in the rest pose with the existing animation removed. We download the chosen animation as an FBX with skin, at 30 fps, without keyframe reduction.&lt;/p&gt;

&lt;p&gt;From there, we retarget locally and review the result. Some clips go back through Blender for adaptation; the combat lab can retarget and adjust timing directly in the browser. Three.js loads the character as GLB, while our shared runtime library loads reusable animation curves separately. That separation matters because adding another action shouldn't require rebuilding every character or hard-coding another preview button.&lt;/p&gt;

&lt;p&gt;Two early combat experiments were Bayonet Stab, used as a spear thrust, and Great Sword Downward Slash. The source motions felt leisurely for the attacks we wanted. We tried a 1.5× overall speed, then compressed the actual strike interval further. The sword experiment also shortens part of the preparation.&lt;/p&gt;

&lt;p&gt;We are leaving those attack clips out of this showcase while we correct the weapon presentation. Those settings are tuning choices for these clips. Different actions need different preparation and recovery. The combat previews still need work on weapon grip and character-specific contact; a convincing swing alone doesn't implement combat.&lt;/p&gt;

&lt;h2&gt;
  
  
  What Blender Truth and Saccade helped us see
&lt;/h2&gt;

&lt;p&gt;The visual and scene-inspection features below are from our Saccade development build. They are not included in the published 0.2.2 package / 0.4.7 Extension. This is a progress report, not a new release announcement.&lt;/p&gt;

&lt;p&gt;Blender Truth gives the agent structured access to Blender state and operations. Saccade handles browser interaction and lets us inspect the running WebGL preview, including sampled image sequences and the application's reported animation state. We also used it to select and download the Mixamo candidates.&lt;/p&gt;

&lt;p&gt;The two views answer different questions. Blender can expose geometry and attachment measurements. Browser footage shows the exported character under the actual runtime animation, lighting, and camera. We need both, and we still have to interpret the evidence carefully.&lt;/p&gt;

&lt;p&gt;The shirt supplied a good example. We gave the goblin a loose, coarse-cloth tunic with rolled sleeves and small neckline details. A front view looked reasonable. Weight checks didn't raise an obvious problem. Later inspection showed a neckline detail floating away from the shirt, with a measured gap around 8.5–9 mm in the sampled poses.&lt;/p&gt;

&lt;p&gt;We had not measured the attachment gap before calling the detail fixed. There is also a trap in using minimum distance alone: one end of a detail may touch while the other lifts away. We changed the neckline stitches into faces integral to the garment and added an attachment check across explicit animation frames. It reports maximum separation and the worst sampled frame and vertex, so a touching tip can't hide a raised end.&lt;/p&gt;

&lt;p&gt;That check has limits. Sampled frames don't cover every instant, and unsigned surface distance doesn't prove that nothing penetrates. We pair the numbers with side-view motion inspection. The agent missed the original problem; the useful result was a better repair and a more specific check.&lt;/p&gt;

&lt;p&gt;We're now able to spend more time on what the residents do. We'd like the next clips to show Mududu managing his inn, Kakka finding useful work, and the consequences of leaving the safety of town. There are still feet, hands, clothes, and transitions to fix along the way. At least we can now trace those problems through the same pipeline we'll use for the next character and the next action.&lt;/p&gt;

&lt;p&gt;We're building &lt;a href="https://github.com/nanlogic/saccade" rel="noopener noreferrer"&gt;Saccade in public on GitHub&lt;/a&gt;. The &lt;a href="https://github.com/nanlogic/saccade/tree/main/docs/showcase/2026-09-16" rel="noopener noreferrer"&gt;development showcase&lt;/a&gt; includes the clips and the limits of what we tested.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Written with AI assistance from our development notes; the examples are from our own project.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>3d</category>
      <category>agents</category>
      <category>ai</category>
      <category>gamedev</category>
    </item>
    <item>
      <title>Stop AI agents from reviving old project decisions</title>
      <dc:creator>Wayne Ma</dc:creator>
      <pubDate>Wed, 02 Sep 2026 02:47:30 +0000</pubDate>
      <link>https://dev.to/sacravenger/stop-ai-agents-from-reviving-old-project-decisions-46ol</link>
      <guid>https://dev.to/sacravenger/stop-ai-agents-from-reviving-old-project-decisions-46ol</guid>
      <description>&lt;p&gt;Long-running repositories collect Markdown files that disagree about what is current. Once Codex, Claude, and humans work across many sessions, an old architecture note can quietly become "the plan" again.&lt;/p&gt;

&lt;p&gt;Markdown Gatekeeper keeps one current revision per topic. Competing docs stay proposals; superseded sources remain recoverable.&lt;/p&gt;

&lt;p&gt;Local-first. Plain Markdown and Git. No account or cloud service.&lt;br&gt;
&lt;/p&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;-g&lt;/span&gt; github:nanlogic/markdown-gatekeeper
mdg setup codex
mdg init &lt;span class="nb"&gt;.&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Source: &lt;a href="https://github.com/nanlogic/markdown-gatekeeper" rel="noopener noreferrer"&gt;https://github.com/nanlogic/markdown-gatekeeper&lt;/a&gt;&lt;/p&gt;

</description>
      <category>agents</category>
      <category>ai</category>
      <category>documentation</category>
      <category>markdown</category>
    </item>
    <item>
      <title>Your AI Can Write the Sales Email. Can You Trust It to Click Send?</title>
      <dc:creator>Wayne Ma</dc:creator>
      <pubDate>Mon, 31 Aug 2026 18:20:40 +0000</pubDate>
      <link>https://dev.to/sacravenger/your-ai-can-write-the-sales-email-can-you-trust-it-to-click-send-2njn</link>
      <guid>https://dev.to/sacravenger/your-ai-can-write-the-sales-email-can-you-trust-it-to-click-send-2njn</guid>
      <description>&lt;p&gt;Ask AI to write a sales email and it can finish before you take a sip of coffee.&lt;/p&gt;

&lt;p&gt;Ask it to open the right account, update the CRM, attach the right file, change a status, click Save, and confirm the change—and the babysitting begins.&lt;/p&gt;

&lt;p&gt;Every browser click becomes a tiny trust exercise.&lt;/p&gt;

&lt;p&gt;Is this the right customer? Is the page still current? Did the button move after a rerender? Did Save actually work? If the connection dropped after the click, will the Agent do it twice?&lt;/p&gt;

&lt;p&gt;This is the browser gap. AI is already good at talking about work. Finishing work inside real browser tabs is harder.&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%2F3iem6z8tmy1mwm053dvo.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%2F3iem6z8tmy1mwm053dvo.gif" alt="Saccade gives an AI one authorized tab, sends small page changes, checks the current target locally, and returns a verified action receipt." width="600" height="375"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The loop is simple: the Agent owns one authorized tab, reads the current page, receives small changes, acts on the current object, and gets evidence back.&lt;/p&gt;

&lt;h2&gt;
  
  
  The work nobody wants to supervise
&lt;/h2&gt;

&lt;p&gt;Sales and operations teams live in CRMs, partner portals, support tools, recruiting systems, product dashboards, and old admin pages.&lt;/p&gt;

&lt;p&gt;The repetitive work sounds easy:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;research a prospect and update the account;&lt;/li&gt;
&lt;li&gt;move a lead to the right stage;&lt;/li&gt;
&lt;li&gt;prepare outreach, then record what happened;&lt;/li&gt;
&lt;li&gt;upload an asset and check the required options;&lt;/li&gt;
&lt;li&gt;work through a long form without losing progress.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These jobs are tedious for people and surprisingly risky for Agents. Two records can look almost identical. A modern form can replace a control while keeping it visually unchanged. An old portal may mix rich text, iframes, uploads, dynamic choices, and a separate Save button.&lt;/p&gt;

&lt;p&gt;The worst failure is uncertainty. An action may have happened just before a timeout. Retrying could create a duplicate message, upload, or submission. Refusing to retry means the person has to inspect the page anyway.&lt;/p&gt;

&lt;p&gt;That is why we built &lt;a href="https://github.com/nanlogic/saccade" rel="noopener noreferrer"&gt;Saccade&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Give the Agent a tab it can be responsible for
&lt;/h2&gt;

&lt;p&gt;Saccade is a live browser Truth and verified-action layer for AI Agents working in authorized Chrome and Edge tabs.&lt;/p&gt;

&lt;p&gt;An Agent knows exactly which tab it owns. It can ask for the current semantic page or only the changes since its last read. When it acts, it uses a current page object—a field, button, choice, table, upload control, or rich-text editor—instead of guessing from an old page description.&lt;/p&gt;

&lt;p&gt;The result comes back with a receipt. Saccade reports whether the action was accepted and whether the expected page change was observed.&lt;/p&gt;

&lt;p&gt;If the object was replaced, the old authority stays stale. If an action may have happened but cannot be verified, the outcome stays unknown and Saccade does not quietly replay it.&lt;/p&gt;

&lt;p&gt;In practical terms, the Agent gets clear answers to four questions:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Which tab am I working in?&lt;/li&gt;
&lt;li&gt;Is this still the object I meant to use?&lt;/li&gt;
&lt;li&gt;Did the action take effect?&lt;/li&gt;
&lt;li&gt;Is it safe to try again?&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;That is what starts to turn browser automation from a demo into work you can hand off.&lt;/p&gt;

&lt;h2&gt;
  
  
  Use it where the browser is actually the best route
&lt;/h2&gt;

&lt;p&gt;Saccade is the browser layer underneath an Agent, not a replacement for every API and integration.&lt;/p&gt;

&lt;p&gt;If a purpose-built API can complete a job faster and more reliably, use it. Saccade is for the steps that genuinely live in the browser: authenticated back offices, partner sites, legacy tools, and interfaces that have no useful connector.&lt;/p&gt;

&lt;p&gt;For sales, that may be the last mile between researched information and a correctly updated account. For operations, it may be a product listing, an upload flow, or a partner portal. For an automation builder, it means the Agent can work in the user's real session without receiving a free-form browser remote control.&lt;/p&gt;

&lt;h2&gt;
  
  
  We tested the part people usually wave away
&lt;/h2&gt;

&lt;p&gt;The Saccade 0.2.0 release candidate went through the same blocking gates in Chrome and Edge: forms, semantic tables, iframe rich text, uploads, reconnects, replaced controls, multiple Agent sessions, and fast moving targets.&lt;/p&gt;

&lt;p&gt;In the Mouse Accuracy gate, it completed 96 of 96 exact-target actions across the two browsers. Mean action latency in those runs ranged from 7.22 ms to 8.50 ms. The &lt;a href="https://github.com/nanlogic/saccade/blob/main/docs/reports/2026-08-30-saccade-0.2.0-release-gate.md" rel="noopener noreferrer"&gt;release evidence&lt;/a&gt; keeps those numbers attached to their test conditions.&lt;/p&gt;

&lt;p&gt;Playwright was an important reference for strict resolution, actionability, assertions, and isolation. It remains an excellent choice for reproducible browser tests. Saccade focuses on a different job: keeping an Agent attached to the user's current, authorized browser state and returning evidence about what changed.&lt;/p&gt;

&lt;h2&gt;
  
  
  Try Saccade 0.2.1
&lt;/h2&gt;

&lt;p&gt;The Node package is public on npm:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npx &lt;span class="nt"&gt;-y&lt;/span&gt; @nanlogic/saccade &lt;span class="nb"&gt;install
&lt;/span&gt;npx &lt;span class="nt"&gt;-y&lt;/span&gt; @nanlogic/saccade doctor
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The source, Extension build, setup guide, and release evidence are public:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/nanlogic/saccade" rel="noopener noreferrer"&gt;GitHub repository&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/nanlogic/saccade/releases/tag/v0.2.1" rel="noopener noreferrer"&gt;Saccade 0.2.1 release&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.npmjs.com/package/@nanlogic/saccade" rel="noopener noreferrer"&gt;npm package&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://chromewebstore.google.com/detail/saccade/gbjapdcoclbdjpcaogmjdbpmnmfgombn" rel="noopener noreferrer"&gt;Chrome Web Store extension&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If your AI can already write the email but you still have to watch every browser click, this is the problem we want to solve.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>automation</category>
      <category>productivity</category>
      <category>opensource</category>
    </item>
  </channel>
</rss>
