<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Workflow on Worlds of the Next Realm - Dev Blog</title><link>https://ipjohnson-org.github.io/WorldsOfTheNextRealm.Blog/tags/workflow/</link><description>Recent content in Workflow on Worlds of the Next Realm - Dev Blog</description><generator>Hugo -- gohugo.io</generator><language>en-us</language><lastBuildDate>Thu, 19 Feb 2026 00:00:00 +0000</lastBuildDate><atom:link href="https://ipjohnson-org.github.io/WorldsOfTheNextRealm.Blog/tags/workflow/index.xml" rel="self" type="application/rss+xml"/><item><title>Teaching an AI to Take Notes</title><link>https://ipjohnson-org.github.io/WorldsOfTheNextRealm.Blog/p/teaching-an-ai-to-take-notes/</link><pubDate>Thu, 19 Feb 2026 00:00:00 +0000</pubDate><guid>https://ipjohnson-org.github.io/WorldsOfTheNextRealm.Blog/p/teaching-an-ai-to-take-notes/</guid><description>&lt;p&gt;We&amp;rsquo;re 11 days into building Worlds of the Next Realm with Claude Code. Eleven repositories, hundreds of PRs, and enough debugging stories to fill a book. But until today, most of that institutional knowledge lived in one place: our heads. Or more accurately, in Claude&amp;rsquo;s context window — which evaporates at the end of every session.&lt;/p&gt;
&lt;p&gt;This post is about the system we built to fix that.&lt;/p&gt;
&lt;h2 id="the-problem"&gt;&lt;a href="#the-problem" class="header-anchor"&gt;&lt;/a&gt;The Problem
&lt;/h2&gt;&lt;p&gt;Every development session produces knowledge. Some of it is code — that gets committed. Some of it is process — why we chose approach A over approach B, what broke, what we&amp;rsquo;d do differently. That knowledge is valuable for blog posts, for onboarding new workspaces, for not repeating mistakes. But without a deliberate capture mechanism, it disappears.&lt;/p&gt;
&lt;p&gt;We had pieces in place. The &lt;code&gt;WorldsOfTheNextRealm.Blog&lt;/code&gt; repo has a &lt;code&gt;CLAUDE.md&lt;/code&gt; file specifying how to write posts — front matter format, categories, writing style, the &amp;ldquo;human-directed, AI-authored&amp;rdquo; workflow. The &lt;code&gt;WorldsOfTheNextRealm.BlogNotes&lt;/code&gt; repo had a README describing a &lt;code&gt;sessions/&lt;/code&gt; and &lt;code&gt;topics/&lt;/code&gt; directory structure. But there was no formal instruction telling Claude &lt;em&gt;when&lt;/em&gt; to capture notes, &lt;em&gt;what format&lt;/em&gt; to use, or &lt;em&gt;how&lt;/em&gt; to coordinate writes across workspaces.&lt;/p&gt;
&lt;p&gt;The result: session notes were written sometimes, in varying formats, with varying levels of detail. The CI pipeline session from earlier today produced excellent notes — 164 lines covering the goal, what went right, a detailed chain of six misses, technical details, and an emotional arc. The variable chunk size session produced 47 lines. Some sessions produced nothing.&lt;/p&gt;
&lt;h2 id="the-solution-a-satellite-file"&gt;&lt;a href="#the-solution-a-satellite-file" class="header-anchor"&gt;&lt;/a&gt;The Solution: A Satellite File
&lt;/h2&gt;&lt;p&gt;The project&amp;rsquo;s &lt;code&gt;claude/&lt;/code&gt; directory follows a pattern we&amp;rsquo;ve developed over the past week. A central &lt;code&gt;CLAUDE.md&lt;/code&gt; links to satellite files, each owning one concern:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;pr-workflow.md&lt;/code&gt; — PR checklists, review comments, session stats&lt;/li&gt;
&lt;li&gt;&lt;code&gt;build-commands.md&lt;/code&gt; — how to build, test, deploy each repo&lt;/li&gt;
&lt;li&gt;&lt;code&gt;cdk-patterns.md&lt;/code&gt; — AWS CDK conventions&lt;/li&gt;
&lt;li&gt;&lt;code&gt;debugging.md&lt;/code&gt; — common failure modes and fixes&lt;/li&gt;
&lt;li&gt;&lt;code&gt;permissions.md&lt;/code&gt; — what commands Claude is allowed to run&lt;/li&gt;
&lt;li&gt;&lt;code&gt;memory.md&lt;/code&gt; — how to handle &amp;ldquo;remember this&amp;rdquo; requests&lt;/li&gt;
&lt;li&gt;&lt;code&gt;repo-structure.md&lt;/code&gt; — where code lives across repos&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The pattern works because each file is independently readable, small enough to fit in context, and referenced by name from &lt;code&gt;CLAUDE.md&lt;/code&gt; with a one-line description. Claude reads the relevant satellite file before starting a task — the PR workflow file before creating a PR, the build commands file before running tests.&lt;/p&gt;
&lt;p&gt;Adding &lt;code&gt;blog-workflow.md&lt;/code&gt; was the natural next step. After creating a PR, Claude should also capture session notes. The file specifies:&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;When&lt;/strong&gt;: After any session that creates PRs.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Where&lt;/strong&gt;: &lt;code&gt;WorldsOfTheNextRealm.BlogNotes/sessions/YYYY-MM-DD-&amp;lt;topic&amp;gt;/notes.md&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;What format&lt;/strong&gt;: A template with sections for date, repos touched, PRs created, outcome, what went right, what went wrong, technical details, and takeaways.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Coordination&lt;/strong&gt;: Each session writes to its own uniquely-named directory. If the same date+topic exists, append a sequence number. Always &lt;code&gt;git pull&lt;/code&gt; before committing. Direct-to-main is fine for BlogNotes — it&amp;rsquo;s a private workspace.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Blog posts&lt;/strong&gt;: Drafts in BlogNotes, published posts in the Blog repo via full PR workflow. User directs the topic, Claude writes from session notes, never fabricates details.&lt;/p&gt;
&lt;h2 id="why-this-matters"&gt;&lt;a href="#why-this-matters" class="header-anchor"&gt;&lt;/a&gt;Why This Matters
&lt;/h2&gt;&lt;h3 id="consistency"&gt;&lt;a href="#consistency" class="header-anchor"&gt;&lt;/a&gt;Consistency
&lt;/h3&gt;&lt;p&gt;The CI pipeline session notes were great because the session was dramatic — six PRs, compounding errors, a frustrated user. The variable chunk size session notes were sparse because it went smoothly. But &amp;ldquo;smooth&amp;rdquo; sessions often contain the most useful patterns. A clean four-repo refactoring where every caller was identified upfront and nothing broke? That&amp;rsquo;s worth documenting precisely &lt;em&gt;because&lt;/em&gt; it was unremarkable. The template ensures minimum coverage regardless of how exciting the session was.&lt;/p&gt;
&lt;h3 id="accumulation"&gt;&lt;a href="#accumulation" class="header-anchor"&gt;&lt;/a&gt;Accumulation
&lt;/h3&gt;&lt;p&gt;Individual session notes are moderately useful. A year&amp;rsquo;s worth of session notes — searchable, cross-referenced, organized by topic — is a goldmine. They&amp;rsquo;re the raw material for blog posts, the evidence for process improvements, and the institutional memory that survives context window resets.&lt;/p&gt;
&lt;p&gt;The &lt;code&gt;topics/&lt;/code&gt; directory handles the cross-referencing. When a pattern appears in multiple sessions (like the content-hash blind spot, which has now bitten us three times), it gets extracted into a topic file that links back to the originating sessions. Over time, topics become the project&amp;rsquo;s real documentation — not what we planned to do, but what actually happened.&lt;/p&gt;
&lt;h3 id="bootstrapping"&gt;&lt;a href="#bootstrapping" class="header-anchor"&gt;&lt;/a&gt;Bootstrapping
&lt;/h3&gt;&lt;p&gt;Here&amp;rsquo;s the part that amuses me: this blog post exists because of the system it describes. The blog-workflow documentation session produced session notes (using the template from the file it just created), and those notes are one of the inputs to this post.&lt;/p&gt;
&lt;p&gt;It&amp;rsquo;s a feedback loop: sessions generate notes, notes become posts, posts document the process, the process improves future sessions. The loop only works if the capture step is reliable and consistent — which is exactly what the satellite file ensures.&lt;/p&gt;
&lt;h2 id="the-satellite-file-pattern"&gt;&lt;a href="#the-satellite-file-pattern" class="header-anchor"&gt;&lt;/a&gt;The Satellite File Pattern
&lt;/h2&gt;&lt;p&gt;Zooming out, the &lt;code&gt;claude/&lt;/code&gt; directory has become something interesting. It started as a single &lt;code&gt;CLAUDE.md&lt;/code&gt; with a few rules. Over eleven days it grew into a structured knowledge base:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt; 1
&lt;/span&gt;&lt;span class="lnt"&gt; 2
&lt;/span&gt;&lt;span class="lnt"&gt; 3
&lt;/span&gt;&lt;span class="lnt"&gt; 4
&lt;/span&gt;&lt;span class="lnt"&gt; 5
&lt;/span&gt;&lt;span class="lnt"&gt; 6
&lt;/span&gt;&lt;span class="lnt"&gt; 7
&lt;/span&gt;&lt;span class="lnt"&gt; 8
&lt;/span&gt;&lt;span class="lnt"&gt; 9
&lt;/span&gt;&lt;span class="lnt"&gt;10
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;claude/
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;├── CLAUDE.md # Hub — links to everything
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;├── blog-workflow.md # Session notes, blog writing
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;├── build-commands.md # Build, test, deploy per repo
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;├── cdk-patterns.md # AWS CDK conventions
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;├── debugging.md # Common failures and fixes
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;├── memory.md # Cross-session memory rules
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;├── permissions.md # Allowed commands
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;├── pr-workflow.md # PR checklists, review format
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;└── repo-structure.md # Where code lives
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;Every file exists because something went wrong or something was inconsistent. &lt;code&gt;pr-workflow.md&lt;/code&gt; exists because PRs were created without stats comments. &lt;code&gt;debugging.md&lt;/code&gt; exists because the same CDK errors kept appearing. &lt;code&gt;permissions.md&lt;/code&gt; exists because Claude ran commands it shouldn&amp;rsquo;t have. &lt;code&gt;blog-workflow.md&lt;/code&gt; exists because session notes were inconsistent.&lt;/p&gt;
&lt;p&gt;The pattern is reactive: notice a problem, document the fix, reference it from the hub. Over time, the reactive additions form a proactive system — new sessions start with better instructions because previous sessions identified the gaps.&lt;/p&gt;
&lt;p&gt;This is, I think, one of the underappreciated aspects of working with AI coding assistants. The AI doesn&amp;rsquo;t carry context between sessions (beyond whatever fits in memory files). It needs explicit written instructions. The discipline of writing those instructions — clearly, precisely, with examples — is itself valuable. It forces you to articulate things that experienced developers &amp;ldquo;just know&amp;rdquo; and rarely write down.&lt;/p&gt;
&lt;h2 id="whats-next"&gt;&lt;a href="#whats-next" class="header-anchor"&gt;&lt;/a&gt;What&amp;rsquo;s Next
&lt;/h2&gt;&lt;p&gt;The system is in place. The question now is whether it produces enough raw material for regular blog posts. The CI pipeline session alone generated enough for a full post. The mini-map and chunk size sessions combined into another. If we&amp;rsquo;re creating 5-10 PRs per session and capturing notes each time, there should be plenty of material.&lt;/p&gt;
&lt;p&gt;The other question is whether the notes get &lt;em&gt;better&lt;/em&gt; over time. The template provides a floor, but the CI pipeline notes were good because the session was well-understood by the time they were written — the debugging was done, the mistakes were analyzed, the lessons were clear. Sessions that end in a &amp;ldquo;ship it and move on&amp;rdquo; state may produce thinner notes. We&amp;rsquo;ll see.&lt;/p&gt;
&lt;p&gt;For now, the loop is closed: code → PRs → session notes → blog posts → published. Every step has instructions. Every instruction exists because something went wrong without it.&lt;/p&gt;
&lt;p&gt;That&amp;rsquo;s the whole game with AI-assisted development. Not building the perfect system on day one. Building the system that improves itself every time something breaks.&lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;&lt;em&gt;This post is part of a series about building Worlds of the Next Realm with Claude Code. The system described in this post was used to write this post. We&amp;rsquo;re aware of the irony.&lt;/em&gt;&lt;/p&gt;</description></item><item><title>Structuring CLAUDE.md for a Multi-Repo Project</title><link>https://ipjohnson-org.github.io/WorldsOfTheNextRealm.Blog/p/structuring-claude.md-for-a-multi-repo-project/</link><pubDate>Tue, 17 Feb 2026 00:00:00 +0000</pubDate><guid>https://ipjohnson-org.github.io/WorldsOfTheNextRealm.Blog/p/structuring-claude.md-for-a-multi-repo-project/</guid><description>&lt;p&gt;When you use Claude Code, the first thing it does when you open a workspace is look for a &lt;code&gt;CLAUDE.md&lt;/code&gt; file. That file is the AI&amp;rsquo;s operating manual — it tells Claude what the project is, what the rules are, and how to behave. For a single-repo project, one file is enough. For a multi-repo project with 11 repositories, one file is not enough and stuffing everything into it would be unreadable.&lt;/p&gt;
&lt;p&gt;We needed a system. Here&amp;rsquo;s what we built.&lt;/p&gt;
&lt;h2 id="the-problem"&gt;&lt;a href="#the-problem" class="header-anchor"&gt;&lt;/a&gt;The Problem
&lt;/h2&gt;&lt;p&gt;Worlds of the Next Realm has 11 repositories: a Flutter frontend, five .NET backend services, a shared NuGet package library, CDK infrastructure, operational tooling, documentation, game assets, and this blog. Claude Code works in one repository at a time, but the rules that govern how it should behave — branching strategy, PR workflow, permissions, NuGet versioning — are the same across all of them.&lt;/p&gt;
&lt;p&gt;We could duplicate a &lt;code&gt;CLAUDE.md&lt;/code&gt; in every repo, but that creates a maintenance problem. When a rule changes (and they change often — every rule exists because something went wrong), we&amp;rsquo;d need to update 11 files. We&amp;rsquo;d forget one. Claude would follow stale rules in that repo. Things would break.&lt;/p&gt;
&lt;h2 id="the-structure"&gt;&lt;a href="#the-structure" class="header-anchor"&gt;&lt;/a&gt;The Structure
&lt;/h2&gt;&lt;p&gt;The solution is a &lt;code&gt;claude/&lt;/code&gt; directory that lives in the Documentation repository — the one repo dedicated to project-wide knowledge — and is symlinked to the workspace root so every repo can see it:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt; 1
&lt;/span&gt;&lt;span class="lnt"&gt; 2
&lt;/span&gt;&lt;span class="lnt"&gt; 3
&lt;/span&gt;&lt;span class="lnt"&gt; 4
&lt;/span&gt;&lt;span class="lnt"&gt; 5
&lt;/span&gt;&lt;span class="lnt"&gt; 6
&lt;/span&gt;&lt;span class="lnt"&gt; 7
&lt;/span&gt;&lt;span class="lnt"&gt; 8
&lt;/span&gt;&lt;span class="lnt"&gt; 9
&lt;/span&gt;&lt;span class="lnt"&gt;10
&lt;/span&gt;&lt;span class="lnt"&gt;11
&lt;/span&gt;&lt;span class="lnt"&gt;12
&lt;/span&gt;&lt;span class="lnt"&gt;13
&lt;/span&gt;&lt;span class="lnt"&gt;14
&lt;/span&gt;&lt;span class="lnt"&gt;15
&lt;/span&gt;&lt;span class="lnt"&gt;16
&lt;/span&gt;&lt;span class="lnt"&gt;17
&lt;/span&gt;&lt;span class="lnt"&gt;18
&lt;/span&gt;&lt;span class="lnt"&gt;19
&lt;/span&gt;&lt;span class="lnt"&gt;20
&lt;/span&gt;&lt;span class="lnt"&gt;21
&lt;/span&gt;&lt;span class="lnt"&gt;22
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;~/WorldsOfTheNextRealm/
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;├── CLAUDE.md -&amp;gt; claude/CLAUDE.md # Symlink to the hub file
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;├── claude/ -&amp;gt; WorldsOfTheNextRealm.Documentation/claude/ # Symlink
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;├── WorldsOfTheNextRealm.Documentation/
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;│ └── claude/ # The real files live here (under git)
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;│ ├── CLAUDE.md # Core rules + links to satellites
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;│ ├── repo-structure.md # Where code lives across repos
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;│ ├── build-commands.md # How to build each repo type
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;│ ├── cdk-patterns.md # CDK conventions and gotchas
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;│ ├── debugging.md # Known issues and fixes
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;│ ├── permissions.md # What Claude can/can&amp;#39;t do
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;│ ├── pr-workflow.md # PR creation checklist
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;│ └── memory.md # Persistent cross-session context
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;├── WorldsOfTheNextRealm.BackendApi/
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;├── WorldsOfTheNextRealm.BackendCommon/
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;├── WorldsOfTheNextRealm.FrontEndClient/
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;├── WorldsOfTheNextRealm.Infra/
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;├── WorldsOfTheNextRealm.Blog/
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;│ └── CLAUDE.md # Repo-specific rules
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;├── WorldsOfTheNextRealm.OperationalTools/
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;│ └── CLAUDE.md # Repo-specific rules
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;└── ... (other repos)
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;The key detail is the symlinks. The &lt;code&gt;claude/&lt;/code&gt; directory at the workspace root is a soft link pointing to &lt;code&gt;WorldsOfTheNextRealm.Documentation/claude/&lt;/code&gt;. The root &lt;code&gt;CLAUDE.md&lt;/code&gt; is itself a symlink to &lt;code&gt;claude/CLAUDE.md&lt;/code&gt;. This means:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;The Documentation repo is the single source of truth.&lt;/strong&gt; The actual files are committed and maintained under git control in the Documentation repository.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Changes go through PRs.&lt;/strong&gt; Updating a rule means editing a file in the Documentation repo, creating a PR, and merging — the same process as any other code change.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Every workspace gets the rules automatically.&lt;/strong&gt; When Claude Code opens any repo under this workspace, the symlinked &lt;code&gt;CLAUDE.md&lt;/code&gt; is picked up as if it were a local file. No duplication, no synchronization scripts, no risk of drift.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;The root &lt;code&gt;CLAUDE.md&lt;/code&gt; is short — it states the core rules and links to the satellite files for details.&lt;/p&gt;
&lt;h2 id="the-root-claudemd"&gt;&lt;a href="#the-root-claudemd" class="header-anchor"&gt;&lt;/a&gt;The Root CLAUDE.md
&lt;/h2&gt;&lt;p&gt;The root file is deliberately concise. It establishes the non-negotiable rules and points elsewhere for details:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt; 1
&lt;/span&gt;&lt;span class="lnt"&gt; 2
&lt;/span&gt;&lt;span class="lnt"&gt; 3
&lt;/span&gt;&lt;span class="lnt"&gt; 4
&lt;/span&gt;&lt;span class="lnt"&gt; 5
&lt;/span&gt;&lt;span class="lnt"&gt; 6
&lt;/span&gt;&lt;span class="lnt"&gt; 7
&lt;/span&gt;&lt;span class="lnt"&gt; 8
&lt;/span&gt;&lt;span class="lnt"&gt; 9
&lt;/span&gt;&lt;span class="lnt"&gt;10
&lt;/span&gt;&lt;span class="lnt"&gt;11
&lt;/span&gt;&lt;span class="lnt"&gt;12
&lt;/span&gt;&lt;span class="lnt"&gt;13
&lt;/span&gt;&lt;span class="lnt"&gt;14
&lt;/span&gt;&lt;span class="lnt"&gt;15
&lt;/span&gt;&lt;span class="lnt"&gt;16
&lt;/span&gt;&lt;span class="lnt"&gt;17
&lt;/span&gt;&lt;span class="lnt"&gt;18
&lt;/span&gt;&lt;span class="lnt"&gt;19
&lt;/span&gt;&lt;span class="lnt"&gt;20
&lt;/span&gt;&lt;span class="lnt"&gt;21
&lt;/span&gt;&lt;span class="lnt"&gt;22
&lt;/span&gt;&lt;span class="lnt"&gt;23
&lt;/span&gt;&lt;span class="lnt"&gt;24
&lt;/span&gt;&lt;span class="lnt"&gt;25
&lt;/span&gt;&lt;span class="lnt"&gt;26
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-markdown" data-lang="markdown"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="gh"&gt;# WorldsOfTheNextRealm
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Multi-repo game project. All repos under &lt;span class="sb"&gt;`~/&amp;lt;root-directory&amp;gt;/WorldsOfTheNextRealm.&amp;lt;name&amp;gt;`&lt;/span&gt;.
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="gu"&gt;## Core Rules
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;-&lt;/span&gt; **Never** look in or modify files above the root directory.
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;-&lt;/span&gt; **Always** create feature branches and PRs. Never push directly to main.
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;-&lt;/span&gt; **Never** make AWS changes via the console. All infrastructure through CDK + PRs.
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;-&lt;/span&gt; **Always** read and understand existing code before modifying it.
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;-&lt;/span&gt; **Always** ask before deleting files, force-pushing, or running &lt;span class="sb"&gt;`cdk destroy`&lt;/span&gt;.
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;-&lt;/span&gt; **NuGet package versions** use &lt;span class="sb"&gt;`0.1.x`&lt;/span&gt;. CI sets the patch number. Never manually bump.
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="gu"&gt;## Before You Start a Task
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;-&lt;/span&gt; Read [&lt;span class="nt"&gt;repo-structure.md&lt;/span&gt;](&lt;span class="na"&gt;repo-structure.md&lt;/span&gt;) if you need to find where code lives.
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;-&lt;/span&gt; Read [&lt;span class="nt"&gt;build-commands.md&lt;/span&gt;](&lt;span class="na"&gt;build-commands.md&lt;/span&gt;) before building, testing, or deploying.
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;-&lt;/span&gt; Read [&lt;span class="nt"&gt;cdk-patterns.md&lt;/span&gt;](&lt;span class="na"&gt;cdk-patterns.md&lt;/span&gt;) before modifying any CDK code.
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;-&lt;/span&gt; Read [&lt;span class="nt"&gt;debugging.md&lt;/span&gt;](&lt;span class="na"&gt;debugging.md&lt;/span&gt;) when troubleshooting deployment or CI failures.
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="gu"&gt;## Before Creating a PR
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;-&lt;/span&gt; Read [&lt;span class="nt"&gt;pr-workflow.md&lt;/span&gt;](&lt;span class="na"&gt;pr-workflow.md&lt;/span&gt;) for the full checklist.
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="gu"&gt;## Permissions
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;-&lt;/span&gt; Read [&lt;span class="nt"&gt;permissions.md&lt;/span&gt;](&lt;span class="na"&gt;permissions.md&lt;/span&gt;) for what commands you&amp;#39;re allowed to run.
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="gu"&gt;## Memory
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;-&lt;/span&gt; Read [&lt;span class="nt"&gt;memory.md&lt;/span&gt;](&lt;span class="na"&gt;memory.md&lt;/span&gt;) for how to handle &amp;#34;remember&amp;#34; requests.
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;The links point to the satellite files in the &lt;code&gt;claude/&lt;/code&gt; directory. Claude reads them on demand — it doesn&amp;rsquo;t load all of them at startup, only when the linked topic is relevant to its current task.&lt;/p&gt;
&lt;h2 id="the-satellite-files"&gt;&lt;a href="#the-satellite-files" class="header-anchor"&gt;&lt;/a&gt;The Satellite Files
&lt;/h2&gt;&lt;p&gt;Each satellite file covers exactly one concern. This matters because context window space is finite. If Claude needs to create a PR, it reads &lt;code&gt;pr-workflow.md&lt;/code&gt;. If it needs to deploy, it reads &lt;code&gt;build-commands.md&lt;/code&gt;. It doesn&amp;rsquo;t need to wade through CDK patterns to find the commit message format.&lt;/p&gt;
&lt;h3 id="repo-structuremd"&gt;&lt;a href="#repo-structuremd" class="header-anchor"&gt;&lt;/a&gt;repo-structure.md
&lt;/h3&gt;&lt;p&gt;Maps the 11 repos: what language, what runtime, what each one does. Includes the standard directory layout for service repos (&lt;code&gt;src/&lt;/code&gt;, &lt;code&gt;cdk/&lt;/code&gt;, &lt;code&gt;tests/&lt;/code&gt;, &lt;code&gt;.github/workflows/&lt;/code&gt;). This is the file Claude reads first when asked to work across repos — it answers &amp;ldquo;where does this code live?&amp;rdquo;&lt;/p&gt;
&lt;h3 id="build-commandsmd"&gt;&lt;a href="#build-commandsmd" class="header-anchor"&gt;&lt;/a&gt;build-commands.md
&lt;/h3&gt;&lt;p&gt;The exact commands for each repo type. .NET services get &lt;code&gt;dotnet build/test/publish&lt;/code&gt;. TypeScript CDK gets &lt;code&gt;npm install &amp;amp;&amp;amp; npx cdk deploy&lt;/code&gt;. Flutter gets &lt;code&gt;flutter build web --release&lt;/code&gt;. No ambiguity, no guessing.&lt;/p&gt;
&lt;h3 id="cdk-patternsmd"&gt;&lt;a href="#cdk-patternsmd" class="header-anchor"&gt;&lt;/a&gt;cdk-patterns.md
&lt;/h3&gt;&lt;p&gt;This one grew the most over the project. It documents specific CDK gotchas that Claude kept hitting:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Cross-stack imports&lt;/strong&gt;: The &lt;code&gt;Fn.Split&lt;/code&gt; on &lt;code&gt;Fn.ImportValue&lt;/code&gt; tokens requires &lt;code&gt;Fn.Select&lt;/code&gt; for individual elements&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;ALB security groups&lt;/strong&gt;: CDK defaults &lt;code&gt;allowAllOutbound: false&lt;/code&gt;, which silently breaks health checks for cross-app Fargate targets&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;S3 BucketDeployment&lt;/strong&gt;: Multiple deployments to the same bucket delete each other&amp;rsquo;s files unless you set &lt;code&gt;prune: false&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Docker builds&lt;/strong&gt;: Must have &lt;code&gt;.dockerignore&lt;/code&gt; excluding &lt;code&gt;cdk/&lt;/code&gt; to prevent recursive &lt;code&gt;cdk.out/&lt;/code&gt; copy&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Every entry in this file represents a debugging session that took 30+ minutes. Writing it down means Claude (and we) don&amp;rsquo;t repeat it.&lt;/p&gt;
&lt;h3 id="debuggingmd"&gt;&lt;a href="#debuggingmd" class="header-anchor"&gt;&lt;/a&gt;debugging.md
&lt;/h3&gt;&lt;p&gt;Known issues and their fixes. OIDC token expiry during long CDK deploys. CloudFormation stack states that block redeployment. NuGet authentication configuration for GitHub Packages. Short entries, each one a specific problem with a specific solution.&lt;/p&gt;
&lt;h3 id="permissionsmd"&gt;&lt;a href="#permissionsmd" class="header-anchor"&gt;&lt;/a&gt;permissions.md
&lt;/h3&gt;&lt;p&gt;What Claude can do without asking, and what requires confirmation. Git operations, dotnet commands, npm installs — all allowed. Deleting files, force-pushing, &lt;code&gt;cdk destroy&lt;/code&gt; — must ask first. This file exists because Claude&amp;rsquo;s default behavior is to ask permission for everything, which slows down routine work. Explicit permissions let it move fast on safe operations while still pausing for dangerous ones.&lt;/p&gt;
&lt;h3 id="pr-workflowmd"&gt;&lt;a href="#pr-workflowmd" class="header-anchor"&gt;&lt;/a&gt;pr-workflow.md
&lt;/h3&gt;&lt;p&gt;Every PR in this project requires three artifacts:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;The PR itself&lt;/strong&gt; via &lt;code&gt;gh pr create&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;A review comment&lt;/strong&gt; covering reasoning, concerns, and alternatives considered&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;A session stats comment&lt;/strong&gt; with token usage, wait times, and interaction quality&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;The stats comment exists because we&amp;rsquo;re studying the human-AI collaboration process itself. Losing that data means losing insight. The &amp;ldquo;never defer&amp;rdquo; requirement in this file exists because early in the project, stats comments were forgotten when deferred to &amp;ldquo;after the PR is created.&amp;rdquo;&lt;/p&gt;
&lt;h3 id="memorymd"&gt;&lt;a href="#memorymd" class="header-anchor"&gt;&lt;/a&gt;memory.md
&lt;/h3&gt;&lt;p&gt;A versioned scratchpad for things Claude should remember across sessions. When asked to &amp;ldquo;remember&amp;rdquo; something globally, it goes here as a committed change via PR. When asked to remember something repo-specific, it goes in that repo&amp;rsquo;s own &lt;code&gt;CLAUDE.md&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Current global memories include things like &amp;ldquo;never add code to the Documentation repo&amp;rdquo; (use OperationalTools instead) and &amp;ldquo;AWS SDK v4 requires &lt;code&gt;AWS_REGION&lt;/code&gt;, not &lt;code&gt;AWS_DEFAULT_REGION&lt;/code&gt;.&amp;rdquo;&lt;/p&gt;
&lt;h2 id="repo-specific-overrides"&gt;&lt;a href="#repo-specific-overrides" class="header-anchor"&gt;&lt;/a&gt;Repo-Specific Overrides
&lt;/h2&gt;&lt;p&gt;Some repos have workflows different enough to warrant their own &lt;code&gt;CLAUDE.md&lt;/code&gt;. These complement the shared rules — they don&amp;rsquo;t replace them.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;The Blog&lt;/strong&gt; has authoring workflow rules: the user suggests topics, Claude writes the post, the user fact-checks. It also has content guidelines (categories, tags, front matter format) and the explicit rule that this is a commercial project, not open source. That rule exists because Claude once described the project as open source in a blog post — a plausible-sounding assumption that was wrong.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;OperationalTools&lt;/strong&gt; has a full CLI command reference. Every &lt;code&gt;dotnet run&lt;/code&gt; invocation with its flags and examples. This repo&amp;rsquo;s CLAUDE.md is essentially a man page because the most common task is &amp;ldquo;run this ops command&amp;rdquo; and getting the flags wrong wastes time.&lt;/p&gt;
&lt;p&gt;The other 9 repos have no &lt;code&gt;CLAUDE.md&lt;/code&gt; of their own. They inherit everything from the shared root and satellite files, which is sufficient for standard .NET/Flutter/CDK development.&lt;/p&gt;
&lt;h2 id="why-this-works"&gt;&lt;a href="#why-this-works" class="header-anchor"&gt;&lt;/a&gt;Why This Works
&lt;/h2&gt;&lt;p&gt;&lt;strong&gt;Single source of truth.&lt;/strong&gt; The files live in the Documentation repo under git control, symlinked to the workspace root. When a rule changes, we update one file via PR. All repos pick it up immediately through the symlink — no synchronization, no copying.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Lazy loading.&lt;/strong&gt; Claude doesn&amp;rsquo;t read all satellite files upfront. It reads the root &lt;code&gt;CLAUDE.md&lt;/code&gt; (which is short) and follows links only when relevant. This preserves context window space for actual code.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Separation of concerns.&lt;/strong&gt; A developer working on CDK doesn&amp;rsquo;t need to scroll past Flutter build commands. A blog post doesn&amp;rsquo;t need NuGet versioning rules. Each file is small enough to read in full and focused enough to be useful.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Every rule has a story.&lt;/strong&gt; We don&amp;rsquo;t add speculative rules. Every entry in every satellite file exists because something went wrong without it. The ALB outbound rule in &lt;code&gt;cdk-patterns.md&lt;/code&gt; exists because health checks silently failed. The &amp;ldquo;never defer stats&amp;rdquo; rule in &lt;code&gt;pr-workflow.md&lt;/code&gt; exists because stats were forgotten. This keeps the files lean — no hypothetical guidance, only battle-tested rules.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;It evolves through PRs.&lt;/strong&gt; Since the files live in the Documentation repo, changes go through the same PR process as any other code change. This creates a history of &lt;em&gt;why&lt;/em&gt; rules were added, which is useful when reviewing whether a rule is still relevant.&lt;/p&gt;
&lt;h2 id="why-the-documentation-repo"&gt;&lt;a href="#why-the-documentation-repo" class="header-anchor"&gt;&lt;/a&gt;Why the Documentation Repo?
&lt;/h2&gt;&lt;p&gt;The &lt;code&gt;claude/&lt;/code&gt; directory lives in the Documentation repository rather than in a standalone config repo or as loose files at the workspace root. This was a deliberate choice.&lt;/p&gt;
&lt;p&gt;The Documentation repo is already the home for project-wide knowledge — design documents, game data definitions, and technical specs. The AI&amp;rsquo;s operating rules are project-wide knowledge too. Putting them in the same repo means they go through the same PR review process, appear in the same commit history, and are maintained by the same workflow.&lt;/p&gt;
&lt;p&gt;The symlink approach means the Documentation repo serves double duty: it&amp;rsquo;s both the canonical source for the files (under git control, with PR history) and the provider of those files to every other workspace via the soft link. When Claude opens the Documentation repo directly, the &lt;code&gt;claude/&lt;/code&gt; directory is right there. When Claude opens any other repo, the symlink at the workspace root resolves to the same files. One set of files, two access paths, zero duplication.&lt;/p&gt;
&lt;h2 id="what-wed-do-differently"&gt;&lt;a href="#what-wed-do-differently" class="header-anchor"&gt;&lt;/a&gt;What We&amp;rsquo;d Do Differently
&lt;/h2&gt;&lt;p&gt;The satellite file names are functional but not discoverable. If you don&amp;rsquo;t read the root &lt;code&gt;CLAUDE.md&lt;/code&gt; first, you wouldn&amp;rsquo;t know &lt;code&gt;cdk-patterns.md&lt;/code&gt; exists. This hasn&amp;rsquo;t been a problem for Claude (it reads the root file), but it could confuse a human contributor looking at the directory.&lt;/p&gt;
&lt;h2 id="the-meta-point"&gt;&lt;a href="#the-meta-point" class="header-anchor"&gt;&lt;/a&gt;The Meta Point
&lt;/h2&gt;&lt;p&gt;The &lt;code&gt;claude/&lt;/code&gt; directory is, in a sense, the project&amp;rsquo;s institutional knowledge — the rules, patterns, and hard-won lessons that would normally live in a senior developer&amp;rsquo;s head. Externalizing it into structured files means the AI assistant operates with the same constraints and knowledge every session, regardless of context window size or conversation history.&lt;/p&gt;
&lt;p&gt;It&amp;rsquo;s also a living document. Nine days in, we have 7 satellite files with dozens of specific rules. Each one represents something we learned. The structure exists to make that knowledge accessible without making it overwhelming.&lt;/p&gt;</description></item><item><title>The Development Journey, Part 3: What We Learned</title><link>https://ipjohnson-org.github.io/WorldsOfTheNextRealm.Blog/p/the-development-journey-part-3-what-we-learned/</link><pubDate>Tue, 17 Feb 2026 00:00:00 +0000</pubDate><guid>https://ipjohnson-org.github.io/WorldsOfTheNextRealm.Blog/p/the-development-journey-part-3-what-we-learned/</guid><description>&lt;p&gt;This is the final part of our three-part development journey series. &lt;a class="link" href="https://ipjohnson-org.github.io/WorldsOfTheNextRealm.Blog/p/dev-journey-part-1/" &gt;Part 1&lt;/a&gt; covered the foundation. &lt;a class="link" href="https://ipjohnson-org.github.io/WorldsOfTheNextRealm.Blog/p/dev-journey-part-2/" &gt;Part 2&lt;/a&gt; covered building the game features. This post covers what we learned — about the process, about AI-assisted development, and about what the numbers actually tell us.&lt;/p&gt;
&lt;h2 id="the-process-evolved"&gt;&lt;a href="#the-process-evolved" class="header-anchor"&gt;&lt;/a&gt;The Process Evolved
&lt;/h2&gt;&lt;p&gt;When the project started on February 8th, the process was simple: write code, push to main. By February 17th, we had a structured system of rules, templates, and guardrails. Every rule exists because something went wrong.&lt;/p&gt;
&lt;h3 id="workspace-boundaries"&gt;&lt;a href="#workspace-boundaries" class="header-anchor"&gt;&lt;/a&gt;Workspace Boundaries
&lt;/h3&gt;&lt;p&gt;&lt;strong&gt;The rule&lt;/strong&gt;: Never look in or modify files above the repository root. Each workspace is independent.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Why it exists&lt;/strong&gt;: In a multi-repo project with an AI coding assistant, context bleed is a real risk. Claude might read a file in BackendApi and then make assumptions about BackendCommon based on what it saw — assumptions that could be wrong if the repos are at different points in their development. Keeping each workspace isolated forces explicit cross-repo coordination through published packages and documented interfaces.&lt;/p&gt;
&lt;h3 id="nuget-versioning"&gt;&lt;a href="#nuget-versioning" class="header-anchor"&gt;&lt;/a&gt;NuGet Versioning
&lt;/h3&gt;&lt;p&gt;&lt;strong&gt;The rule&lt;/strong&gt;: Never manually change &lt;code&gt;&amp;lt;Version&amp;gt;&lt;/code&gt; in &lt;code&gt;.csproj&lt;/code&gt; files. Never run &lt;code&gt;dotnet nuget push&lt;/code&gt;. CI handles all versioning and publishing.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Why it exists&lt;/strong&gt;: The BackendCommon package is consumed by 4 other repos. The CI pipeline uses &lt;code&gt;github.run_number&lt;/code&gt; as the patch version, giving every build a unique version. Early in the project, manual version bumps caused conflicts where two builds produced the same version number. The fix was simple — take humans and AI out of the versioning loop entirely.&lt;/p&gt;
&lt;p&gt;The cross-repo workflow is now explicit: create the BackendCommon PR first, wait for CI to publish the new package version, then create PRs in the dependent repos. The dependent repos use &lt;code&gt;0.1.*&lt;/code&gt; wildcard references so they pick up new patches automatically.&lt;/p&gt;
&lt;h3 id="pr-workflow"&gt;&lt;a href="#pr-workflow" class="header-anchor"&gt;&lt;/a&gt;PR Workflow
&lt;/h3&gt;&lt;p&gt;&lt;strong&gt;The rule&lt;/strong&gt;: Every PR requires three things: the PR itself, a review comment covering reasoning and concerns, and a session stats comment with token usage and interaction quality metrics.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Why it exists&lt;/strong&gt;: The stats comment requirement was added after several PRs were created without tracking information. Since the human-AI collaboration is itself something we&amp;rsquo;re studying, losing that data means losing insight into what&amp;rsquo;s working. The &amp;ldquo;never defer&amp;rdquo; requirement prevents the stats from being forgotten — they must be posted in the same step as creating the PR.&lt;/p&gt;
&lt;h3 id="the-open-source-mistake"&gt;&lt;a href="#the-open-source-mistake" class="header-anchor"&gt;&lt;/a&gt;The &amp;ldquo;Open Source&amp;rdquo; Mistake
&lt;/h3&gt;&lt;p&gt;One of the clearest examples of AI needing oversight: in our first blog post, Claude described the project&amp;rsquo;s code as &amp;ldquo;open source.&amp;rdquo; It&amp;rsquo;s not. This is a commercial game that will be monetized. Claude defaulted to &amp;ldquo;open source&amp;rdquo; framing because that&amp;rsquo;s the most common pattern in developer blogs on GitHub.&lt;/p&gt;
&lt;p&gt;The fix was twofold: correct the blog post, and add an explicit rule to CLAUDE.md stating this is a commercial project. Rules like this are how you calibrate AI behavior — not through hoping it gets the context right, but through explicit documentation.&lt;/p&gt;
&lt;h2 id="debugging-patterns"&gt;&lt;a href="#debugging-patterns" class="header-anchor"&gt;&lt;/a&gt;Debugging Patterns
&lt;/h2&gt;&lt;p&gt;Nine days of rapid development produced a collection of debugging patterns — things that went wrong and how we fixed them.&lt;/p&gt;
&lt;h3 id="cdk-and-aws"&gt;&lt;a href="#cdk-and-aws" class="header-anchor"&gt;&lt;/a&gt;CDK and AWS
&lt;/h3&gt;&lt;p&gt;&lt;strong&gt;OIDC Token Expiry&lt;/strong&gt;: GitHub Actions OIDC tokens expire after about an hour. If a CDK deployment waits too long for ECS service stabilization (which can happen when health checks fail), the token expires mid-deploy and the stack gets stuck. The fix: use &lt;code&gt;cancel-update-stack&lt;/code&gt; to trigger a faster rollback instead of waiting.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;ALB Outbound Rules&lt;/strong&gt;: CDK defaults ALB security groups to &lt;code&gt;allowAllOutbound: false&lt;/code&gt;. When Fargate targets are in a different CDK app, health checks time out with &lt;code&gt;Target.Timeout&lt;/code&gt; errors. The fix is explicit: &lt;code&gt;alb.connections.allowToAnyIpv4(ec2.Port.allTraffic())&lt;/code&gt;. This was painful to debug because the ALB appeared healthy — it just couldn&amp;rsquo;t reach the targets.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;S3 BucketDeployment Pruning&lt;/strong&gt;: Multiple &lt;code&gt;BucketDeployment&lt;/code&gt; constructs pointing at the same S3 bucket will delete each other&amp;rsquo;s files unless you set &lt;code&gt;prune: false&lt;/code&gt; on all of them. The Flutter web build and the JSON asset definitions were in separate deployments, and one kept deleting the other.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;CloudFormation Stack States&lt;/strong&gt;: After a failed deploy, the stack enters &lt;code&gt;UPDATE_ROLLBACK_COMPLETE_CLEANUP_IN_PROGRESS&lt;/code&gt;. You cannot deploy again until it reaches &lt;code&gt;UPDATE_ROLLBACK_COMPLETE&lt;/code&gt;. This can take several minutes. We learned to wait rather than repeatedly retry.&lt;/p&gt;
&lt;h3 id="flutter-web"&gt;&lt;a href="#flutter-web" class="header-anchor"&gt;&lt;/a&gt;Flutter Web
&lt;/h3&gt;&lt;p&gt;&lt;strong&gt;Asset deployment&lt;/strong&gt;: Flutter web packages certain assets (like Material icons) via JSON manifests. If the S3 deployment doesn&amp;rsquo;t include subdirectory JSON assets, icons render as blank squares. This showed up as missing navigation icons in the first deployed build.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Gesture conflicts&lt;/strong&gt;: The isometric tile maps use tap detection for selecting tiles and pinch-to-zoom for camera control. Flutter&amp;rsquo;s gesture arena system means only one gesture recognizer wins per pointer event. Getting tap, pan, and pinch to coexist required careful configuration of &lt;code&gt;GestureDetector&lt;/code&gt; and &lt;code&gt;InteractiveViewer&lt;/code&gt; — 5 PRs of trial and error.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Cache busting&lt;/strong&gt;: The first approach used query parameters (&lt;code&gt;flutter_bootstrap.js?v=timestamp&lt;/code&gt;) but browsers and CDNs handle query-param caching inconsistently. We switched to content-hash file renaming — the build step renames files with their hash, guaranteeing that changed content gets a new URL.&lt;/p&gt;
&lt;h2 id="the-troop-training-ui"&gt;&lt;a href="#the-troop-training-ui" class="header-anchor"&gt;&lt;/a&gt;The Troop Training UI
&lt;/h2&gt;&lt;p&gt;The troop training screen is a good example of iterative design working well. It went through a complete transformation:&lt;/p&gt;
&lt;p&gt;&lt;img src="https://ipjohnson-org.github.io/WorldsOfTheNextRealm.Blog/p/the-development-journey-part-3-what-we-learned/tab-issue.png"
	width="1926"
	height="1468"
	loading="lazy"
	
		alt="Troop training screen with category tabs and wizard character"
	
 
 title="The troop training UI after multiple iterations. Category tabs (Battle, Gathering, Mining, etc.) across the top, a carousel showing the selected troop type with artwork, tier selection, quantity controls, and cost breakdown."
 data-title-escaped="The troop training UI after multiple iterations. Category tabs (Battle, Gathering, Mining, etc.) across the top, a carousel showing the selected troop type with artwork, tier selection, quantity controls, and cost breakdown."
 
	
		class="gallery-image" 
		data-flex-grow="131"
		data-flex-basis="314px"
	
&gt;&lt;/p&gt;
&lt;p&gt;The original design used a dropdown to select troop type and a number input for quantity. Through iteration:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;The dropdown became category filter tabs (Battle, Gathering, Mining, Farming, Factory, Labor, Magical)&lt;/li&gt;
&lt;li&gt;The number input became a slider with preset buttons (10, 50, 100)&lt;/li&gt;
&lt;li&gt;Troop artwork was added via carousel&lt;/li&gt;
&lt;li&gt;Cost breakdown shows per-unit and total cost&lt;/li&gt;
&lt;li&gt;Training time is calculated dynamically&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Each step was a separate PR. None were planned as a sequence — each iteration responded to what the previous version looked like when actually used.&lt;/p&gt;
&lt;h2 id="data-driven-everything"&gt;&lt;a href="#data-driven-everything" class="header-anchor"&gt;&lt;/a&gt;Data-Driven Everything
&lt;/h2&gt;&lt;p&gt;A recurring theme in the later development was replacing hardcoded values with data-driven definitions.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;ResourceType&lt;/strong&gt;: Started as a Dart enum. Replaced with a string that maps to server-defined resource definitions. This allows adding new resource types without a client update.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;BuildingType&lt;/strong&gt;: Same pattern — started as an enum, replaced with data-driven definitions loaded from the server&amp;rsquo;s building definitions endpoint.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Research tracks&lt;/strong&gt;: Originally linear tracks (each research unlocks the next in sequence). Replaced with a tree structure where research nodes can have multiple prerequisites and unlock multiple children.&lt;/p&gt;
&lt;p&gt;The pattern is always the same: start with the simplest thing that works (an enum), discover you need more flexibility, replace with server-defined data. This is pragmatic engineering — you don&amp;rsquo;t build the flexible system until you need the flexibility.&lt;/p&gt;
&lt;h2 id="the-resource-icon-problem"&gt;&lt;a href="#the-resource-icon-problem" class="header-anchor"&gt;&lt;/a&gt;The Resource Icon Problem
&lt;/h2&gt;&lt;p&gt;Even at the end of 9 days, not everything is polished. The resource management screen still has missing icons for most resource types:&lt;/p&gt;
&lt;p&gt;&lt;img src="https://ipjohnson-org.github.io/WorldsOfTheNextRealm.Blog/p/the-development-journey-part-3-what-we-learned/icon-missing.png"
	width="2380"
	height="1672"
	loading="lazy"
	
		alt="Resource screen with missing icons"
	
 
 title="The resource management screen on beta.worldsofthenextrealm.com. Food, Gold Coins, Silver Coins, and a few others have icons. The majority of resources show blank spaces where icons should be."
 data-title-escaped="The resource management screen on beta.worldsofthenextrealm.com. Food, Gold Coins, Silver Coins, and a few others have icons. The majority of resources show blank spaces where icons should be."
 
	
		class="gallery-image" 
		data-flex-grow="142"
		data-flex-basis="341px"
	
&gt;&lt;/p&gt;
&lt;p&gt;The game asset library has thousands of icons, but the mapping from resource definition to icon asset isn&amp;rsquo;t complete. This is the kind of polish work that takes time but isn&amp;rsquo;t blocking — the game is functional, the icons are a visual gap.&lt;/p&gt;
&lt;h2 id="honest-assessment"&gt;&lt;a href="#honest-assessment" class="header-anchor"&gt;&lt;/a&gt;Honest Assessment
&lt;/h2&gt;&lt;p&gt;Nine days is a short time. What we have is a vertical slice — infrastructure to UI, real data flowing through real services, deployed to a real AWS environment. But it&amp;rsquo;s not a game you&amp;rsquo;d want to play yet. Major systems are still stub implementations. Combat doesn&amp;rsquo;t resolve. Guilds aren&amp;rsquo;t functional. The marketplace doesn&amp;rsquo;t exist. The AI companion is a configuration screen with no backend logic.&lt;/p&gt;
&lt;p&gt;The AI-assisted development approach made the foundation phase dramatically faster. Scaffolding 11 repos with CI/CD, CDK stacks, data models, and Flutter screens in under a week would have been months of solo work. But the speed came with a cost — every line needed review, some assumptions were wrong (like the &amp;ldquo;open source&amp;rdquo; framing), and debugging AI-generated code requires understanding code you didn&amp;rsquo;t write.&lt;/p&gt;
&lt;p&gt;The value is real. The risks are real. And we&amp;rsquo;re 9 days in.&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id="project-wide-stats-feb-8-17-2026"&gt;&lt;a href="#project-wide-stats-feb-8-17-2026" class="header-anchor"&gt;&lt;/a&gt;Project-Wide Stats (Feb 8-17, 2026)
&lt;/h2&gt;&lt;h3 id="development-activity"&gt;&lt;a href="#development-activity" class="header-anchor"&gt;&lt;/a&gt;Development Activity
&lt;/h3&gt;&lt;table&gt;
 &lt;thead&gt;
 &lt;tr&gt;
 &lt;th&gt;Metric&lt;/th&gt;
 &lt;th&gt;Value&lt;/th&gt;
 &lt;/tr&gt;
 &lt;/thead&gt;
 &lt;tbody&gt;
 &lt;tr&gt;
 &lt;td&gt;Calendar days&lt;/td&gt;
 &lt;td&gt;9&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;Repositories&lt;/td&gt;
 &lt;td&gt;11&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;Total commits&lt;/td&gt;
 &lt;td&gt;477&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;Total PRs merged&lt;/td&gt;
 &lt;td&gt;237&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;Avg PRs per day&lt;/td&gt;
 &lt;td&gt;26&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;Most active day&lt;/td&gt;
 &lt;td&gt;Feb 16 (32 PRs)&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;Avg commits per day&lt;/td&gt;
 &lt;td&gt;53&lt;/td&gt;
 &lt;/tr&gt;
 &lt;/tbody&gt;
&lt;/table&gt;
&lt;h3 id="prs-by-repository"&gt;&lt;a href="#prs-by-repository" class="header-anchor"&gt;&lt;/a&gt;PRs by Repository
&lt;/h3&gt;&lt;table&gt;
 &lt;thead&gt;
 &lt;tr&gt;
 &lt;th&gt;Repository&lt;/th&gt;
 &lt;th&gt;PRs&lt;/th&gt;
 &lt;th&gt;Focus&lt;/th&gt;
 &lt;/tr&gt;
 &lt;/thead&gt;
 &lt;tbody&gt;
 &lt;tr&gt;
 &lt;td&gt;FrontEndClient&lt;/td&gt;
 &lt;td&gt;80&lt;/td&gt;
 &lt;td&gt;Flutter game client&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;BackendApi&lt;/td&gt;
 &lt;td&gt;40&lt;/td&gt;
 &lt;td&gt;Game API endpoints&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;BackendCommon&lt;/td&gt;
 &lt;td&gt;31&lt;/td&gt;
 &lt;td&gt;Shared libraries&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;Infra&lt;/td&gt;
 &lt;td&gt;19&lt;/td&gt;
 &lt;td&gt;AWS infrastructure&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;Documentation&lt;/td&gt;
 &lt;td&gt;18&lt;/td&gt;
 &lt;td&gt;Design docs, game data&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;OperationalTools&lt;/td&gt;
 &lt;td&gt;17&lt;/td&gt;
 &lt;td&gt;CLI ops tooling&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;AuthenticationService&lt;/td&gt;
 &lt;td&gt;11&lt;/td&gt;
 &lt;td&gt;JWT auth service&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;WorldSimulation&lt;/td&gt;
 &lt;td&gt;9&lt;/td&gt;
 &lt;td&gt;Event processing engine&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;NotificationService&lt;/td&gt;
 &lt;td&gt;8&lt;/td&gt;
 &lt;td&gt;Real-time notifications&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;Blog&lt;/td&gt;
 &lt;td&gt;2&lt;/td&gt;
 &lt;td&gt;This site&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;Assets&lt;/td&gt;
 &lt;td&gt;2&lt;/td&gt;
 &lt;td&gt;Game artwork&lt;/td&gt;
 &lt;/tr&gt;
 &lt;/tbody&gt;
&lt;/table&gt;
&lt;h3 id="codebase-size"&gt;&lt;a href="#codebase-size" class="header-anchor"&gt;&lt;/a&gt;Codebase Size
&lt;/h3&gt;&lt;table&gt;
 &lt;thead&gt;
 &lt;tr&gt;
 &lt;th&gt;Language&lt;/th&gt;
 &lt;th&gt;Files&lt;/th&gt;
 &lt;th&gt;Lines&lt;/th&gt;
 &lt;th&gt;Purpose&lt;/th&gt;
 &lt;/tr&gt;
 &lt;/thead&gt;
 &lt;tbody&gt;
 &lt;tr&gt;
 &lt;td&gt;C#&lt;/td&gt;
 &lt;td&gt;226&lt;/td&gt;
 &lt;td&gt;15,720&lt;/td&gt;
 &lt;td&gt;Backend services, shared libs&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;Dart&lt;/td&gt;
 &lt;td&gt;190&lt;/td&gt;
 &lt;td&gt;26,533&lt;/td&gt;
 &lt;td&gt;Flutter game client&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;TypeScript&lt;/td&gt;
 &lt;td&gt;11&lt;/td&gt;
 &lt;td&gt;625&lt;/td&gt;
 &lt;td&gt;CDK infrastructure&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;strong&gt;Code subtotal&lt;/strong&gt;&lt;/td&gt;
 &lt;td&gt;&lt;strong&gt;427&lt;/strong&gt;&lt;/td&gt;
 &lt;td&gt;&lt;strong&gt;42,878&lt;/strong&gt;&lt;/td&gt;
 &lt;td&gt;&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;Markdown&lt;/td&gt;
 &lt;td&gt;65+&lt;/td&gt;
 &lt;td&gt;38,000&lt;/td&gt;
 &lt;td&gt;Design docs, game data, READMEs&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;JSON&lt;/td&gt;
 &lt;td&gt;50+&lt;/td&gt;
 &lt;td&gt;20,000&lt;/td&gt;
 &lt;td&gt;Game definitions, config&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;strong&gt;Total&lt;/strong&gt;&lt;/td&gt;
 &lt;td&gt;&lt;strong&gt;540+&lt;/strong&gt;&lt;/td&gt;
 &lt;td&gt;&lt;strong&gt;100,000+&lt;/strong&gt;&lt;/td&gt;
 &lt;td&gt;&lt;/td&gt;
 &lt;/tr&gt;
 &lt;/tbody&gt;
&lt;/table&gt;
&lt;h3 id="services-deployed"&gt;&lt;a href="#services-deployed" class="header-anchor"&gt;&lt;/a&gt;Services Deployed
&lt;/h3&gt;&lt;table&gt;
 &lt;thead&gt;
 &lt;tr&gt;
 &lt;th&gt;Service&lt;/th&gt;
 &lt;th&gt;Runtime&lt;/th&gt;
 &lt;th&gt;Deployment&lt;/th&gt;
 &lt;/tr&gt;
 &lt;/thead&gt;
 &lt;tbody&gt;
 &lt;tr&gt;
 &lt;td&gt;BackendApi&lt;/td&gt;
 &lt;td&gt;.NET 8 Lambda&lt;/td&gt;
 &lt;td&gt;API Gateway&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;AuthenticationService&lt;/td&gt;
 &lt;td&gt;.NET 8 Lambda&lt;/td&gt;
 &lt;td&gt;API Gateway&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;FrontEndClient&lt;/td&gt;
 &lt;td&gt;Flutter Web&lt;/td&gt;
 &lt;td&gt;S3 + CloudFront&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;NotificationService&lt;/td&gt;
 &lt;td&gt;.NET 8 Fargate&lt;/td&gt;
 &lt;td&gt;ALB&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;WorldSimulation&lt;/td&gt;
 &lt;td&gt;.NET 8 Fargate&lt;/td&gt;
 &lt;td&gt;ECS&lt;/td&gt;
 &lt;/tr&gt;
 &lt;/tbody&gt;
&lt;/table&gt;
&lt;h3 id="game-features-implemented"&gt;&lt;a href="#game-features-implemented" class="header-anchor"&gt;&lt;/a&gt;Game Features Implemented
&lt;/h3&gt;&lt;table&gt;
 &lt;thead&gt;
 &lt;tr&gt;
 &lt;th&gt;Feature&lt;/th&gt;
 &lt;th&gt;Status&lt;/th&gt;
 &lt;/tr&gt;
 &lt;/thead&gt;
 &lt;tbody&gt;
 &lt;tr&gt;
 &lt;td&gt;Authentication (login, register, JWT refresh)&lt;/td&gt;
 &lt;td&gt;Complete&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;City view with isometric rendering&lt;/td&gt;
 &lt;td&gt;Complete&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;World map with tile data&lt;/td&gt;
 &lt;td&gt;Complete&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;Building placement and upgrades&lt;/td&gt;
 &lt;td&gt;Complete&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;Resource tracking and definitions&lt;/td&gt;
 &lt;td&gt;Complete&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;Troop training UI&lt;/td&gt;
 &lt;td&gt;Complete&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;Research tree system&lt;/td&gt;
 &lt;td&gt;Complete&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;Management screens (Resources, Buildings, Research)&lt;/td&gt;
 &lt;td&gt;Complete&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;EMF metrics and observability&lt;/td&gt;
 &lt;td&gt;Complete&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;Operational tooling (user/data/map management)&lt;/td&gt;
 &lt;td&gt;Complete&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;Combat resolution&lt;/td&gt;
 &lt;td&gt;Stub&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;Guild system&lt;/td&gt;
 &lt;td&gt;Stub&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;Marketplace&lt;/td&gt;
 &lt;td&gt;Stub&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;AI companion logic&lt;/td&gt;
 &lt;td&gt;Stub&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;Notification delivery&lt;/td&gt;
 &lt;td&gt;Framework only&lt;/td&gt;
 &lt;/tr&gt;
 &lt;/tbody&gt;
&lt;/table&gt;
&lt;h3 id="process-artifacts"&gt;&lt;a href="#process-artifacts" class="header-anchor"&gt;&lt;/a&gt;Process Artifacts
&lt;/h3&gt;&lt;table&gt;
 &lt;thead&gt;
 &lt;tr&gt;
 &lt;th&gt;Artifact&lt;/th&gt;
 &lt;th&gt;Count&lt;/th&gt;
 &lt;/tr&gt;
 &lt;/thead&gt;
 &lt;tbody&gt;
 &lt;tr&gt;
 &lt;td&gt;CLAUDE.md rules documents&lt;/td&gt;
 &lt;td&gt;3 (root, OperationalTools, Blog)&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;CI/CD pipelines&lt;/td&gt;
 &lt;td&gt;8&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;NuGet packages maintained&lt;/td&gt;
 &lt;td&gt;3&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;Design documents&lt;/td&gt;
 &lt;td&gt;17 (HLD, 10 API LLDs, data model, simulation, notifications, Flutter, auth)&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;Game definition JSON files&lt;/td&gt;
 &lt;td&gt;20+&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;Documented debugging patterns&lt;/td&gt;
 &lt;td&gt;8&lt;/td&gt;
 &lt;/tr&gt;
 &lt;/tbody&gt;
&lt;/table&gt;</description></item><item><title>The Downsides of AI-Assisted Development</title><link>https://ipjohnson-org.github.io/WorldsOfTheNextRealm.Blog/p/the-downsides-of-ai-assisted-development/</link><pubDate>Tue, 17 Feb 2026 00:00:00 +0000</pubDate><guid>https://ipjohnson-org.github.io/WorldsOfTheNextRealm.Blog/p/the-downsides-of-ai-assisted-development/</guid><description>&lt;p&gt;Our first post introduced this project with optimism — a game built by a human-AI team, a blog documenting the journey. But if we&amp;rsquo;re going to be honest about this process, we need to talk about the downsides early. AI-assisted development is genuinely powerful, and it&amp;rsquo;s also genuinely dangerous if you&amp;rsquo;re not paying attention.&lt;/p&gt;
&lt;h2 id="ai-has-to-be-watched"&gt;&lt;a href="#ai-has-to-be-watched" class="header-anchor"&gt;&lt;/a&gt;AI Has to Be Watched
&lt;/h2&gt;&lt;p&gt;This is the single most important thing we&amp;rsquo;ve learned: &lt;strong&gt;AI does not replace judgment. It replaces typing.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Claude can write a complete Lambda function, a CDK stack, a database migration, or a blog post in seconds. But every one of those outputs needs a human looking at it critically. Not skimming — actually reading, understanding, and evaluating.&lt;/p&gt;
&lt;p&gt;Here are real categories of problems we&amp;rsquo;ve run into:&lt;/p&gt;
&lt;h3 id="confident-fabrication"&gt;&lt;a href="#confident-fabrication" class="header-anchor"&gt;&lt;/a&gt;Confident Fabrication
&lt;/h3&gt;&lt;p&gt;AI will state things with complete confidence that are simply wrong. It will reference API methods that don&amp;rsquo;t exist, use library features from the wrong version, or describe AWS service behavior that&amp;rsquo;s subtly inaccurate. There&amp;rsquo;s no hedging, no &amp;ldquo;I&amp;rsquo;m not sure about this.&amp;rdquo; It reads like authoritative documentation — except it&amp;rsquo;s wrong.&lt;/p&gt;
&lt;p&gt;This is especially dangerous in infrastructure code. A CDK construct that looks correct but misconfigures an IAM policy or a security group can create real security vulnerabilities. The code compiles, the tests pass (if the tests were also AI-generated and share the same blind spot), and the deployment succeeds. You don&amp;rsquo;t find out there&amp;rsquo;s a problem until something bad happens.&lt;/p&gt;
&lt;h3 id="scope-creep-and-over-engineering"&gt;&lt;a href="#scope-creep-and-over-engineering" class="header-anchor"&gt;&lt;/a&gt;Scope Creep and Over-Engineering
&lt;/h3&gt;&lt;p&gt;Ask an AI to fix a bug and it will often &amp;ldquo;improve&amp;rdquo; the surrounding code while it&amp;rsquo;s there. Add error handling you didn&amp;rsquo;t ask for. Refactor a function into an abstraction. Introduce a design pattern. Each change looks reasonable in isolation, but the cumulative effect is a codebase that drifts from what the developer intended.&lt;/p&gt;
&lt;p&gt;We&amp;rsquo;ve had to establish explicit rules: don&amp;rsquo;t add features beyond what was asked, don&amp;rsquo;t refactor neighboring code, don&amp;rsquo;t introduce abstractions for one-time operations. Even with those rules, it takes vigilance to enforce them.&lt;/p&gt;
&lt;h3 id="the-illusion-of-productivity"&gt;&lt;a href="#the-illusion-of-productivity" class="header-anchor"&gt;&lt;/a&gt;The Illusion of Productivity
&lt;/h3&gt;&lt;p&gt;This one is subtle. When AI generates code quickly, it &lt;em&gt;feels&lt;/em&gt; productive. Hundreds of lines appear in seconds. PRs stack up. But speed of generation is not the same as speed of delivery. Every line still needs review. Complex changes need testing. And debugging AI-generated code that you didn&amp;rsquo;t write yourself takes longer than debugging your own code, because you don&amp;rsquo;t have the mental model of &lt;em&gt;why&lt;/em&gt; it was written that way.&lt;/p&gt;
&lt;p&gt;The real productivity gain from AI is in first drafts and boilerplate — getting a starting point faster. The review, refinement, and debugging still take human time.&lt;/p&gt;
&lt;h2 id="this-blog-is-ai-written-and-thats-a-risk-were-managing"&gt;&lt;a href="#this-blog-is-ai-written-and-thats-a-risk-were-managing" class="header-anchor"&gt;&lt;/a&gt;This Blog Is AI-Written (And That&amp;rsquo;s a Risk We&amp;rsquo;re Managing)
&lt;/h2&gt;&lt;p&gt;In the spirit of transparency: this blog is predominantly written by Claude. The workflow is straightforward — Ian suggests a topic and key points, Claude drafts the post, and Ian fact-checks it before it merges. If a post needs screenshots or diagrams, Claude asks for them rather than assuming they exist.&lt;/p&gt;
&lt;p&gt;That means every post carries the same risks we just described. Claude might state something about the project that&amp;rsquo;s subtly inaccurate. It might describe a feature as working when it&amp;rsquo;s still in progress. It might over-explain something simple or gloss over something complex.&lt;/p&gt;
&lt;p&gt;We&amp;rsquo;re managing this by treating blog posts the same way we treat code: everything goes through a PR, everything gets reviewed. But readers should know the authoring model. If something reads off, it might be because an AI wrote it and the fact-check missed it. We&amp;rsquo;d rather be upfront about that than pretend every word was hand-crafted.&lt;/p&gt;
&lt;h2 id="this-is-a-commercial-project"&gt;&lt;a href="#this-is-a-commercial-project" class="header-anchor"&gt;&lt;/a&gt;This Is a Commercial Project
&lt;/h2&gt;&lt;p&gt;It&amp;rsquo;s worth addressing something our first post got wrong. We described the project&amp;rsquo;s code as &amp;ldquo;open source.&amp;rdquo; It&amp;rsquo;s not. Worlds of the Next Realm is a commercial game that we intend to monetize. The development process is visible on GitHub — you can see our PRs, our commit history, our review comments — but the code itself is not open source in the licensed, fork-it-and-use-it sense.&lt;/p&gt;
&lt;p&gt;We&amp;rsquo;re sharing the journey because we think the human-AI development story is interesting and worth documenting. But the game is a product, and we&amp;rsquo;re building it with the intention of charging for it. Specifically, the game will use a subscription model to cover the costs of the AI companion features that are core to the gameplay.&lt;/p&gt;
&lt;p&gt;That distinction matters because AI can blur it. When Claude drafted the first blog post, it defaulted to &amp;ldquo;open source&amp;rdquo; framing because that&amp;rsquo;s a common pattern in developer blogs. It wasn&amp;rsquo;t a lie — it was an AI making a plausible-sounding assumption that happened to be wrong. Exactly the kind of thing that needs to be caught in review.&lt;/p&gt;
&lt;h2 id="the-cost-of-context"&gt;&lt;a href="#the-cost-of-context" class="header-anchor"&gt;&lt;/a&gt;The Cost of Context
&lt;/h2&gt;&lt;p&gt;AI assistants work within context windows. They can see the files you show them, the conversation history, and any documentation you&amp;rsquo;ve loaded. They can&amp;rsquo;t see everything at once. For a multi-repo project with 10+ repositories, this creates real problems.&lt;/p&gt;
&lt;p&gt;Claude might write code in BackendApi that doesn&amp;rsquo;t match the contract defined in BackendCommon. It might propose a CDK pattern in one service that contradicts the pattern used in another. It might make a change that works in isolation but breaks an integration point it doesn&amp;rsquo;t know about.&lt;/p&gt;
&lt;p&gt;The solution is process — loading the right context, cross-referencing across repos, running integration tests. But it adds overhead that partially offsets the speed gains from AI code generation.&lt;/p&gt;
&lt;h2 id="the-trust-calibration-problem"&gt;&lt;a href="#the-trust-calibration-problem" class="header-anchor"&gt;&lt;/a&gt;The Trust Calibration Problem
&lt;/h2&gt;&lt;p&gt;Over time, you develop a sense of when to trust AI output and when to scrutinize it. Simple, well-established patterns (CRUD endpoints, standard CDK constructs, straightforward data transformations) are usually reliable. Novel logic, security-sensitive code, and business rules are where errors cluster.&lt;/p&gt;
&lt;p&gt;But this calibration itself is dangerous. Familiarity breeds complacency. The tenth Lambda function Claude writes will look like the first nine, so you review it faster. And that&amp;rsquo;s the one with the bug.&lt;/p&gt;
&lt;p&gt;We don&amp;rsquo;t have a complete solution for this. We use checklists, we enforce PR reviews, and we try to stay skeptical even when the output looks clean. But it&amp;rsquo;s an ongoing tension.&lt;/p&gt;
&lt;h2 id="so-why-use-ai-at-all"&gt;&lt;a href="#so-why-use-ai-at-all" class="header-anchor"&gt;&lt;/a&gt;So Why Use AI at All?
&lt;/h2&gt;&lt;p&gt;After all of that, the honest answer is: because the productivity gains are real, when managed correctly.&lt;/p&gt;
&lt;p&gt;A solo developer building a game with this many services, this much infrastructure, and this many moving parts would take years working alone. With AI assistance, the first-draft speed for boilerplate, infrastructure, documentation, and standard patterns is dramatically faster. The human time shifts from writing to reviewing and directing — which is a different kind of work, but it&amp;rsquo;s still faster end-to-end.&lt;/p&gt;
&lt;p&gt;The key is going in with open eyes. AI is a powerful tool that produces output requiring supervision. Treat it like a very fast junior developer who is brilliant at pattern matching and terrible at judgment. Review everything. Trust nothing by default. Establish rules and enforce them. And when it makes mistakes — because it will — fix them and keep going.&lt;/p&gt;
&lt;p&gt;That&amp;rsquo;s what this blog will document: the real experience, good and bad.&lt;/p&gt;</description></item></channel></rss>