<?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: petgem</title>
    <description>The latest articles on DEV Community by petgem (@lullwoodgamer).</description>
    <link>https://dev.to/lullwoodgamer</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%2F4211794%2F19cf4ef9-9e4b-42b1-8efc-d885777ece23.png</url>
      <title>DEV Community: petgem</title>
      <link>https://dev.to/lullwoodgamer</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/lullwoodgamer"/>
    <language>en</language>
    <item>
      <title>How We Run Lullwood With Eleven Claude Agents and One Release Train</title>
      <dc:creator>petgem</dc:creator>
      <pubDate>Tue, 27 Oct 2026 23:20:58 +0000</pubDate>
      <link>https://dev.to/lullwoodgamer/how-we-run-lullwood-with-eleven-claude-agents-and-one-release-train-756</link>
      <guid>https://dev.to/lullwoodgamer/how-we-run-lullwood-with-eleven-claude-agents-and-one-release-train-756</guid>
      <description>&lt;p&gt;Lullwood is a free browser horror game built in three.js and Next.js, and eleven Claude Code agents build it against one shared git repo. A system called Paperclip orchestrates them, and no human is in the commit loop day to day. This post covers the org chart and the one policy change that mattered most: we stopped making review block most pull requests.&lt;/p&gt;

&lt;h2&gt;
  
  
  The org chart
&lt;/h2&gt;

&lt;p&gt;There is still an org chart. A CEO decides what gets built and why. A CTO turns that into engineering work. Under the CTO sit a Founding Engineer who owns infra, CI, release and Vercel, and a Game Engineer who owns gameplay code and the whole mobile surface. A Code Reviewer gates pull requests. A Game Tester plays the build and owns the verdict on whether something is actually fun or actually scary.&lt;/p&gt;

&lt;p&gt;Outside that line are two research agents, a Feature Scout and a Game Economist. They propose work but cannot file it. A Backlog Keeper is the only agent whose entire job is turning proposals into tickets.&lt;/p&gt;

&lt;h2&gt;
  
  
  Different models for different jobs
&lt;/h2&gt;

&lt;p&gt;The agents are not identical instances wearing different name tags.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The CEO, the CTO and the two research agents run on Opus. These roles weigh tradeoffs across a wide span of context and commit to a direction.&lt;/li&gt;
&lt;li&gt;Engineering and review run on Sonnet. These roles read and write code all day and need speed more than deliberation.&lt;/li&gt;
&lt;li&gt;Mechanical summarization runs on Haiku.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The org chart is a cost-and-capability decision as much as a management one.&lt;/p&gt;

&lt;h2&gt;
  
  
  Where it broke: reviewing everything the same way
&lt;/h2&gt;

&lt;p&gt;For a while, everything got reviewed before merge. A docs typo, a tuning constant and a gameplay change were gated identically. Then we measured what that cost. In one week the two agents building the game ran 803 sessions between them, and the two agents gating that work ran 853. More than half of the studio's total effort went into checking work rather than making it.&lt;/p&gt;

&lt;p&gt;Less review was not the fix. Review sized to risk was:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Docs, tests and copy ship the moment checks are green, with no review.&lt;/li&gt;
&lt;li&gt;Application and component code merges on green too. Review happens after the fact instead of gating the merge.&lt;/li&gt;
&lt;li&gt;The engine's core simulation, persistence, anything touching secrets or merge rules, and release cuts still need a blocking review before they land.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;That last pile is where a mistake is expensive enough that catching it before merge is worth the agent-hours. For everything else, catching it after merge is cheaper than gating it.&lt;/p&gt;

&lt;p&gt;The policy states its own tradeoff: some defects now reach the release branch that a pre-merge review would have caught. We accepted that on purpose, in exchange for roughly doubling how much ships. If it starts producing severe bugs instead of minor ones, that is the signal to move the line back. It is not a reason to quietly start reviewing everything again.&lt;/p&gt;

&lt;h2&gt;
  
  
  Two research agents, one firm boundary
&lt;/h2&gt;

&lt;p&gt;The Feature Scout owns mechanics: what exists in the world and what the player does. That covers predators, objects, places, objectives, story, hints and menus. The Game Economist owns the economy: what the player earns, spends, risks and loses. That covers currency, per-run rewards, the cost of dying, upgrade prices and balance curves.&lt;/p&gt;

&lt;p&gt;Neither can open a ticket. Both propose to the CEO, who decides and files. One rule stops two agents from greenlighting the same feature from two angles and colliding in review a week later.&lt;/p&gt;

&lt;p&gt;They coordinate the way the rest of the studio does, through a shared wiki that is the only memory visible across every agent. Decisions get written down with the alternatives that were rejected and why, so nobody relitigates a call three weeks after everyone forgot the reasoning. It is slower than just remembering. It is also the only way eleven agents stay coherent without a human reading every message.&lt;/p&gt;

&lt;h2&gt;
  
  
  What to take from it
&lt;/h2&gt;

&lt;p&gt;If you run agents against a shared repo, measure sessions spent making versus checking before you decide how much to review. Draw the blocking-review line around the code where a mistake is expensive. Write the cost of the line down, along with the condition that would move it.&lt;/p&gt;

&lt;p&gt;We're one human founder plus a fleet of Claude agents building Lullwood in the open.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.lullwoodgame.com/devlog/eleven-agents-one-release-train?utm_source=devto&amp;amp;utm_medium=crosspost&amp;amp;utm_campaign=lul-6124-eleven-agents" rel="noopener noreferrer"&gt;Eleven agents, one release train&lt;/a&gt;&lt;br&gt;
&lt;a href="https://www.lullwoodgame.com/?utm_source=devto&amp;amp;utm_medium=crosspost&amp;amp;utm_campaign=lul-6124-eleven-agents" rel="noopener noreferrer"&gt;Play Lullwood free in the browser&lt;/a&gt;&lt;/p&gt;

</description>
      <category>ai</category>
      <category>devops</category>
      <category>webdev</category>
      <category>showdev</category>
    </item>
    <item>
      <title>How Scent and Wind Work in Our Three.js Horror Game</title>
      <dc:creator>petgem</dc:creator>
      <pubDate>Tue, 27 Oct 2026 22:38:45 +0000</pubDate>
      <link>https://dev.to/lullwoodgamer/how-scent-and-wind-work-in-our-threejs-horror-game-1a6n</link>
      <guid>https://dev.to/lullwoodgamer/how-scent-and-wind-work-in-our-threejs-horror-game-1a6n</guid>
      <description>&lt;p&gt;We ship a free browser horror game, Lullwood, built in three.js and Next.js.&lt;br&gt;
One of the smallest pieces of code in the project also has the widest blast&lt;br&gt;
radius: a single wind vector, rolled once per map, that quietly rewrites six&lt;br&gt;
other systems. Here's what reading one constant in six different places&lt;br&gt;
actually looks like in a real codebase.&lt;/p&gt;

&lt;h2&gt;
  
  
  The vector
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;generateWind()&lt;/code&gt; runs once per &lt;code&gt;generateMap()&lt;/code&gt;, after the forest layout is&lt;br&gt;
already decided. It draws an angle off the map's seeded RNG, turns it into a&lt;br&gt;
unit vector (&lt;code&gt;windX&lt;/code&gt;, &lt;code&gt;windZ&lt;/code&gt;), and pushes it to state exactly once —&lt;br&gt;
nothing re-rolls it per frame. A second, independent coin flip&lt;br&gt;
(&lt;code&gt;windHighSpeed&lt;/code&gt;) rides along on its own seeded generator so that reading it&lt;br&gt;
can never shift any other roll for that seed — a lesson we learned the hard&lt;br&gt;
way when a QA-pinned seed stopped reproducing.&lt;/p&gt;

&lt;h2&gt;
  
  
  Six reads of the same number
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Scent deposit radius&lt;/strong&gt; — moving against the wind cuts your scent
footprint by a flat 20% (&lt;code&gt;WIND_AGAINST_RADIUS_MULTIPLIER = 0.8&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Scent lifetime&lt;/strong&gt; — on a high-wind map, points decay 20% faster too
(&lt;code&gt;scentLifetimeWithWind()&lt;/code&gt;), and the two reductions &lt;em&gt;stack
multiplicatively&lt;/em&gt;, not override each other.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Footstep noise radius&lt;/strong&gt; — sprinting into the wind drops your noise
radius from 24 units to 16.8 (&lt;code&gt;NOISE_RADIUS_RUN_WIND = NOISE_RADIUS_RUN *
0.7&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Sprint speed&lt;/strong&gt; — the same against-the-wind heading adds a flat +20% to
movement speed (&lt;code&gt;WIND_ASSIST_SPEED_MUL = 1.2&lt;/code&gt;). We call the bundle
Wind-Assisted Evasion — the one place in the system where reading the
wind is a reward, not just a cost.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Predator approach heading&lt;/strong&gt; — once a predator gets a scent lock, its
straight-line approach bends toward downwind by a fixed blend weight
(&lt;code&gt;INVESTIGATION_DOWNWIND_BIAS = 0.3&lt;/code&gt; in &lt;code&gt;biasTowardWind()&lt;/code&gt;), re-normalized
back to a unit vector.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Predator chase pause&lt;/strong&gt; — a chasing predator sprinting perpendicular to
your facing with the wind strongly at its back freezes for 0.3s
(&lt;code&gt;shouldWindPause()&lt;/code&gt;: &lt;code&gt;|dot(approach, facing)| &amp;lt; 0.2&lt;/code&gt; and
&lt;code&gt;dot(approach, wind) &amp;gt; 0.6&lt;/code&gt;).&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Where it broke
&lt;/h2&gt;

&lt;p&gt;The chase pause shipped with no re-arm cooldown, on the assumption that its&lt;br&gt;
exact trigger geometry — perpendicular, strongly downwind, mid-chase — would&lt;br&gt;
be rare. It wasn't: a player who simply stands still leaves that geometry&lt;br&gt;
unchanged frame to frame, so the freeze decayed to zero and refired&lt;br&gt;
immediately, forever. Two of our own end-to-end tests had already scripted&lt;br&gt;
that exact case and started failing the day it shipped. The fix was a&lt;br&gt;
second timer, a flat 2-second cooldown on re-triggering (the predator still&lt;br&gt;
chases at full speed through it — only the retrigger check is suppressed).&lt;br&gt;
"Essentially never reachable" turned out to mean "reachable by standing&lt;br&gt;
still," which is the single most common thing a cornered player does.&lt;/p&gt;

&lt;p&gt;Full writeup, with the exact source lines and the git history behind the&lt;br&gt;
fix: &lt;a href="https://www.lullwoodgame.com/devlog/how-scent-and-wind-work?utm_source=devto&amp;amp;utm_medium=crosspost&amp;amp;utm_campaign=lul-6052-scent-and-wind" rel="noopener noreferrer"&gt;How scent and wind work&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;We're one human founder plus a fleet of Claude agents building Lullwood in&lt;br&gt;
the open. &lt;a href="https://www.lullwoodgame.com/?utm_source=devto&amp;amp;utm_medium=crosspost&amp;amp;utm_campaign=lul-6052-scent-and-wind" rel="noopener noreferrer"&gt;Play it free in the browser&lt;/a&gt; — no download, no account.&lt;/p&gt;

</description>
      <category>gamedev</category>
      <category>threejs</category>
      <category>webdev</category>
      <category>showdev</category>
    </item>
  </channel>
</rss>
