AI-Assisted Development

Everyone’s hyped about the Ralph Wiggum technqiue for Claude Code.

Install it. Write a prompt. Let AI work autonomously for hours. Come back to a finished app. Sounds incredible.

Here’s what actually happens: You write a prompt. Ralph runs for 45 minutes. It declares victory. You check the output. Half the requirements are missing. iOS doesn’t compile. The “persistence” layer saves to memory that vanishes on restart.

What went wrong? Nothing, actually.

Ralph did exactly what you asked. The problem is what you asked for.

Why "Better Prompts" Doesn't Help

The standard advice is “write better prompts.” More detail. More specificity. That’s like saying “write better requirements” when your app has bugs. True, but useless.

Here’s the non-obvious part: Ralph Wiggum is a loop. It runs, checks your success criteria, and keeps going until all criteria pass. That’s it. That’s the whole trick.

Which means everything depends on the criteria. Vague criteria? Ralph satisfies them vaguely and stops. You asked for “app works on all platforms.” It ran on desktop once, saw no crash, declared success. Technically correct.

The skill isn’t “prompt engineering.” It’s criteria design. And there’s a much simpler way to think about it.

part 1
This is Part 1 of a series on building Uno Platform apps with Studio and a Ralph Loop workflow. The big idea in this post: constraints beat instructions.
Next up: the full Ralph Wiggum Loop system, end-to-end.
Subscribe to the Uno Platform blog →

The Reframe: Constraints, Not Wishes

Forget what you want. Focus on what would block your PR.

You already know this list:

  • Does it build on iOS?
  • Does it build on Android?
  • Do the analyzers pass?
  • Are there warnings?
  • Does the app actually launch?

 

These are constraints. Binary. Pass or fail. No interpretation required.

Ralph’s success criteria should be the same thing. Not “works correctly” but “`dotnet build -f net10.0-ios` exits 0.” Not “follows best practices” but “no classes implement INotifyPropertyChanged in the Models folder.”

This is the entire insight. Convert wishes into gates.

The Test: Can a Script Check It?

Here’s a simple filter. For each success criterion, ask: “Can a script verify this?”

If yes, it’s a constraint. If no, it’s a wish.

Wish Constraint
"Works on iOS" dotnet build -f net10.0-ios exits 0
"Uses MVUX correctly" IState<T> found in Model classes
"Responsive design" VisualStateManager defines states at 641px and 1008px
"Data persists" File exists at specific path after app restart
"Good UX" All touch targets MinHeight >= 44

Ralph can grep. Ralph can run build commands. Ralph can check file existence. Ralph cannot evaluate “good.”

Every wish becomes a gate. Every gate is binary. That’s the whole approach.

Three Examples That Actually Work

Let me show you weak criteria, what goes wrong, and how to fix them. All three are Uno Platform scenarios because that’s what I work with, but the pattern applies anywhere.

01 Cross-Platform Build
The Task

Create an Uno Platform app with TabBar navigation.

❌ What you might write
App works on all platforms
No major errors
Navigation functions correctly
✅ What actually works
dotnet build -f net10.0-ios exits 0, zero warnings
dotnet build -f net10.0-android exits 0, zero warnings
dotnet build -f net10.0-desktop exits 0, zero warnings
dotnet build -f net10.0-browserwasm exits 0, zero warnings
TabBar contains min 3 TabBarItem elements in XAML
Each TabBarItem has distinct Content page
No TODO comments in generated code
What happens with vague criteria → Ralph builds it. Runs it once on desktop. Tabs switch. No crash visible. Done. Three weeks later you try the iOS build. Linker error. Android crashes on startup.
02 MVUX State Management
The Task

Implement user preferences with MVUX and persistence.

❌ What you might write
MVUX pattern implemented correctly
Settings persist between sessions
UI updates reactively
✅ What actually works
PreferencesModel.cs uses IState<UserPreferences>
No classes implement INotifyPropertyChanged in Models
Settings serialized to LocalFolder/preferences.json
Persistence test: write, terminate, restart, read
Zero binding errors in debug output
Uno.Extensions.Reactive in csproj
What happens with vague criteria → Ralph uses INotifyPropertyChanged instead of IState<T> because that's more common in training data. Saves settings to a dictionary in memory. "Persists" until you close the app.
03 Responsive Layout
The Task

Dashboard that adapts from mobile to desktop.

❌ What you might write
UI is responsive
Looks good on phone and desktop
Sidebar collapses on small screens
✅ What actually works
VisualStateManager: Compact, Medium, Expanded
AdaptiveTrigger: MinWindowWidth 0, 641, 1008
NavigationView.PaneDisplayMode changes per state
No hardcoded Width in pixels (use Auto or *)
All interactive elements: MinHeight ≥ 44, MinWidth ≥ 44
No horizontal scrollbar at any breakpoint
What happens with vague criteria → Ralph adds Grid columns with arbitrary breakpoints. "Responsive" technically achieved. "Looks good" evaluated by nobody. Sidebar disappears entirely or overlaps content.

The Constraint Stack

Here’s how I build success criteria now. Four layers, in order:

1 Build Gates
dotnet build -f net10.0-ios exits 0
dotnet build -f net10.0-android exits 0
dotnet build -f net10.0-desktop exits 0
dotnet build -f net10.0-browserwasm exits 0
2 Type Contracts
Required types exist where expected (IState, IFeed, interfaces)
Anti-patterns are absent (no INotifyPropertyChanged, no ObservableCollection)
NuGet packages referenced
3 Structural Contracts
Required files exist at expected paths (Models/Task.cs, Services/ITaskService.cs)
Patterns present in specific files (uen:Navigation.Request in page XAML)
Folder structure matches architecture (no code-behind navigation calls)
4 Runtime Verification Contracts
App launches without exception
Specific behavior verified (nav, persistence)
Debug output clean

Stack these. Ralph checks all of them, every loop. If it doesn’t compile on all targets, nothing else matters.

Runtime verification We'll cover runtime UI verification via App MCP screenshots and visual tree inspection in more depth later in this series.

Iteration Budget: A Real Tradeoff

The --max-iterations flag matters more than people realize.

Loose criteria with high iteration cap: Ralph loops forever trying to satisfy something unmeasurable. Burns your usage. Produces garbage. Tight criteria with reasonable cap: Ralph converges fast because exit conditions are clear. 30 iterations is usually enough for a well-specified task.

Tight criteria reduce iteration count, which reduces cost. Vague criteria do the opposite. 

What This Doesn't Fix

Let me be direct about limitations.

Aesthetic judgments: “Looks good” requires eyes. Constrain structure, review visuals yourself.

Performance at scale: “Handles 10K items” or “loads in under 2 seconds” requires load testing. Ralph can build it. You benchmark it.

Security vulnerabilities: XSS, injection, exposure of secrets. Ralph doesn’t audit for these. Run your security tooling separately.

Business logic correctness: “Calculates tax correctly” or “handles edge cases” requires domain knowledge. Constrain the structure, verify the math yourself.

Integration complexity: External APIs, authentication flows, device-specific behavior. Ralph can scaffold. You verify.

The judgment problem: Some decisions are subjective. Ralph will make choices. You might disagree. That’s not a bug.

The pattern: constrain what you can (structure, types, patterns), review what you can’t (aesthetics, security, business logic). 

Remember Autonomous doesn't mean unsupervised. Know when to stop Ralph and review.

Takeaway

Ralph Wiggum isn’t magic. It’s a loop with a termination condition. Your success criteria are that condition.

Vague criteria produce vague results. Binary constraints produce verifiable results. The skill is converting what you want into what can be checked

You already do this for CI pipelines. Do the same thing for Ralph.

Shoutout

Shout out to Geoffrey Hutley, the creator of Ralph and a former contributor to Uno Platform project a few years ago — thanks for building Ralph and pushing the space forward.