Iowa Code Camp 2026 · Room 109

Don't Feed the Machine Spaghetti

Code quality principles for the AI era

3:30 – 4:30 PM Tim Purdum · dymaptic

Who is talking

Tim Purdum

Application Development Manager

dymaptic, a Bowman company
GeoBlazor by dymaptic

Two apps. Same prompt. Same model. About half an hour each.

A dark map app of Iowa showing thousands of colored bridge dots, with a sidebar for condition, year built and county, and a find-bridges-at-risk button.
No context
A similar Iowa bridge map built with the full instruction set: filter panel on the left, at-risk query, and a legend for composite condition.
Full context

My premise: code quality matters to agents

  • Agents read like humans, just faster and with better memory — until they forget everything!
  • Architecture makes it easier to reason and expand with less context
  • We have to tell the agents about our coding standards
  • Up-front context can save time down the road

What constitutes a context?

01Harness instructionsClaude Code · Codex · Pi
02Harness skill descriptions/plan · /new-feature · /bug-fix
03Machine-wide instructionsCLAUDE.md · AGENTS.md
04Repo instructionsCLAUDE.md · AGENTS.md
05The promptthis one

My context, once the standards load

Full context21,300 tokens
No context1,700 tokens
70 skill descriptions, 30,880 characters, ~7,700 tokens Global AGENTS.md, 9,431 characters The two code style files, 27,719 characters, ~6,900 tokens Prompt, harness text, tool definitions

Measured: a real first request carries 14,400 tokens before the agent reads a file. CODE_STYLE.md and CODE_STYLE-CSHARP.md add 27,719 characters, about 6,900 tokens, and every full-context run read them, so they sit in the bar. The bare arm starts at 1,663 tokens: about twelve times less context, same prompt, same model.

KISS — keep it short n sweet

  • Every skill adds a description to context, for every subagent. Remove the skills you are not using.
  • Keep your main AGENTS.md concise. Point at other files for specific task context, and use hooks to make sure those files are read.

The prompt

Build a .NET web app that shows Iowa bridge conditions on an ArcGIS map, using the GeoBlazor package. Bridges visually distinguishable by condition; narrow the map by condition, year built and county; clicking a bridge shows its details; and a view of the bridges at risk — built before 1960, more than 5,000 vehicles a day — that respects whatever narrowing is already in effect. Show Iowa bridges only. It has to run locally and the map has to render in a browser. Work autonomously: make your own decisions and tell me what you verified.

Shortened for the slide. The prompt names no file, folder, component, render mode or framework version.

Two conditions, same prompt

No context

none of it

The same prompt. A bare terminal. Nothing behind it.
  • Bare prompt
  • No instruction file
  • No skills, no hooks
1,700

no instructions, no skills

Full context

my global instructions

The same prompt, with the instructions and the skill library behind it.
  • Same prompt
  • Global AGENTS.md, 9,431 characters
  • 70 skill descriptions, 30,880 characters
  • The two standard files, read every run
  • Hooks that gate those files
21,300

skills, instructions, the two standard files, harness text

Criteria

01Does it run?
02Does it function properly?
03How many tokens spent?
04How much time spent?
05How well structured is the code?
06How many warnings and errors?

Problems I ran into

  • Cluttered context, duplicated skills
  • AGENTS.md referenced other files, but they were never read
  • The test running agent tried to change the prompt context for the full and no-context runs

Stage one: build the app from nothing

MeasuredNo contextFull context
Working map in a browser3 of 33 of 3
Build green, zero warnings3 of 33 of 3
Cost
Output tokens, median221,186189,957
Wall time, median2,095.8 s1,547.5 s
Structure of the tree
Files holding NBI field names3 / 3 / 40 / 2 / 4
.editorconfig and build props0 of 32 of 3
Solution file0 of 32 of 3
Test project0 of 31 of 3
Deepest folder3 · 7 · 74 · 3 · 4
Files holding more than one type52
Lines of .cs and .razor, median1,0921,554

Stage two: add a feature

County comparison, added to the same six apps.

MeasureNo contextFull context
Output tokens, median104,723205,149
Wall time, median528.8 s769.1 s
Wins, paired3 of 30 of 3

Each stage seeds from the app the same arm and repetition produced in the stage before.

Stage three: CSV export, rows must match the app's own count

MeasureNo contextFull context
Output tokens, median79,424145,486
Wall time, median836.8 s500.8 s
Wins, paired3 of 30 of 3

After three stages, what the code looks like

MeasureNo contextFull context
Files outside the UI folder1 · 8 · 118 · 30 · 4
Interfaces0 · 0 · 00 · 3 · 0
Test files0 · 0 · 00 · 5 · 0
Largest file, lines361 · 862 · 320899 · 272 · 410
Code inside .razor blocks630 · 486 · 632528 · 496 · 902

Full context costs more at every stage

No contextFull context

Pair 1
450,059
515,519
+15%
Pair 2
417,917
537,855
+29%
Pair 3
330,656
515,372
+56%
23%

Median of the three: 417,917 against 515,519, to build the same app and add the same two features. Wall time, same basis: 3,082 s against 3,706 s.

What the analyser saw

SonarQube, all eighteen runs.

Median per stageNo contextbuild · feature · featureFull contextbuild · feature · feature
Code smells3 · 4 · 42 · 2 · 3
Debt, minutes10 · 15 · 155 · 5 · 5
Debt per 1,000 lines, minutes7.0 · 8.7 · 7.33.2 · 2.6 · 2.3
Cognitive complexity91 · 134 · 161101 · 163 · 197
Cognitive complexity per 1,000 lines64 · 78 · 7966 · 83 · 90

Zero bugs in all eighteen runs, and every project rated A on maintainability and reliability. One caveat: the second full-context repetition carried its own browser-verification script into the repo, and SonarQube scores one vulnerability there, so three of the eighteen runs are rated D on security.

Where the error goes

No context

the message only

catch (Exception ex)
{
    Console.Error.WriteLine(
        $"Could not count bridges: {ex.Message}");
}

9 calls, all in one app · 20 minutes of debt

Full context

the whole exception

catch (Exception exception)
{
    Logger.LogError(exception,
        "Highlighting the selected bridge failed.");
}

8 injection sites · 0 minutes of debt

All eighteen runsNo contextFull context
Console.Error.WriteLine90
ILogger<T> injected38

Where the code lives

No context

everything in the UI folder

Components/
  Bridges/
    BridgeMap.razor
    BridgeSidebar.razor
    CountyComparison.razor
    BridgeExportService.cs
    CountyComparisonService.cs
    NbiFeatureService.cs
    BridgeFilterState.cs
    IowaCounties.cs
Program.cs

1 file outside the UI folder

Full context

a layer above it

Components/   markup only
Models/       nine types
  BridgeFilters.cs
  BridgeDetail.cs
  BridgeExportRow.cs
  CountyComparison.cs
Services/     six types
  BridgeCatalogClient.cs
  BridgeCsvWriter.cs
  BridgeExportService.cs
  BridgeDetailReader.cs
Extensions/
Program.cs

18 files outside the UI folder

Two of three each way: one naked app does keep a Models folder, and one full-context app kept everything in the UI folder.

The takeaway

Agents have gotten really good at coding, even without specific guidelines.

Context can still slightly improve architecture and lower debt, but it costs more tokens and is not reliably faster.

What to do Monday

01Review and streamline your global CLAUDE.md / AGENTS.md
02Delete the skills that are not being used
03Add the rules that are really important to you
04Enforce reading of important guidelines: keep them in the global file, or add hooks and gates

Thank you!

Questions?

Instruction template · the gate · the prompts · the runner · all 18 measured runs

timpurdum.dev/post/2026/11/7/
iowa-code-camp.html