Code decisions
What 534 uroboro captures reveal about coding patterns
February 2026
Uroboro captures decisions in "X over Y — reason" format. Every time a choice is made between approaches, the decision goes into the trail. Over months, this accumulates into a map of coding preferences that were never written down as rules but emerge from repeated choices.
This page analyzes 534 captures from the last 90 days across 9 projects. Not all are decisions — some are blockers, questions, and general captures. But the decisions are the richest signal. They show what was chosen, what was rejected, and why.
Dependency avoidance
highest frequencyThe single most recurring pattern across all projects. When a choice exists between adding a dependency and writing a simpler in-house version, the in-house version wins unless the dependency provides significant, non-trivial functionality.
Duplication is explicitly accepted when the alternative introduces coupling or external dependencies. Keeping things self-contained is a first-class design goal. The threshold question isn't "does a library exist?" but "is the library's complexity justified by what we'd have to write ourselves?"
State minimalism
cross-projectA preference for the smallest possible state representation. Derive what you can, store only what you must. This sometimes means reversing earlier decisions when they prove unnecessarily complex.
The interesting pattern here is the willingness to reverse. The FractalNode tree was built, then torn out when a simpler model proved sufficient. Mutable shared state was refactored to parameterized statelessness. The aesthetic is "notice when the model is more complex than the problem requires" — and then simplify.
Extraction threshold
contextualWhen to extract a function vs. keep it inline isn't a simple "three uses = extract" rule. The decision depends on domain ownership and layer coherence, not just repetition count.
But the opposite also happens:
Extract when: the pattern is identical, both sites are in the same domain, and the extracted function lives near the domain logic it serves. Don't extract when: the function is small, extraction would create cross-layer coupling, and the duplication is stable (unlikely to diverge). Three similar lines of code is better than a premature abstraction.
Framework pragmatism
repeatedMultiple captures record discovering that a clean abstraction doesn't work with the actual framework, and choosing the pragmatic workaround over fighting the system.
Follow the grain of the existing system. When a theoretically cleaner approach conflicts with how the framework actually behaves, the pragmatic path wins. This applies to file formats, template inheritance, routing conventions — the system you have constrains the system you want. Attempting clean abstractions that the framework doesn't support is a waste of effort.
Ship with imprecision
philosophicalA recurring willingness to ship with known limitations rather than block on unavailable perfect data. The imprecision is always documented.
Defaults at the balance point of extremes. Ship with documented imprecision rather than block on perfect data. The critical qualifier is "documented" — acknowledged limitations are fine, silent inaccuracies are not. This applies to scoring heuristics, tool descriptions, and any claim made in writing.
Iterative precision
two-directionalRegex patterns and detection logic follow a distinct refinement pattern: broaden first to catch edge cases, then tighten when false positives appear. Both directions are captured with the specific failure mode that triggered the change.
First release is intentionally broad to discover what the pattern actually looks like in the wild. Then tighten based on observed false positives. The captures record both directions and both failure modes. This is how the prompt-profile classifier itself evolved — from 50.7% imperative detection down to 16.5% as the heuristics got sharper.
Real over mock
testingTesting decisions consistently prefer real system interaction over mocked substitutes, and implementation sequencing is chosen to unblock testability early.
Prefer testing against real systems over mocks when feasible. Mocks are a last resort, not a default. And when planning implementation order, choose the sequence that unblocks testability earliest — even if it means building feature B before feature A.
Rewrite threshold
rare but clearRewriting from scratch is not the default. But when architectures are genuinely incompatible, incremental migration creates more adapter code than the rewrite would produce.
Rewrite when the constraints are genuinely incompatible — wrong database bindings, wrong UI paradigm, wrong schema. The test isn't "could we migrate?" but "would the migration code be more complex than the new implementation?" When the answer is yes, start clean.
The pattern table
Eight themes distilled from 534 captures. None were planned. All emerged from repeated choices.
Dependencies
Avoid by default. Accept duplication when it preserves self-containment.
State
Minimal, derived. Revisit when complexity proves unjustified.
Extraction
By domain ownership and layer coherence, not just reuse count.
Framework
Follow the grain. Constraints of the existing system win over clean abstractions.
Shipping
Ship with documented imprecision. Block only on genuinely missing data.
Precision
Broaden first, tighten on false positives. Both directions captured.
Testing
Real systems over mocks. Sequence implementation to enable early testability.
Rewriting
Only when architectures are genuinely incompatible. Migration code > new code = rewrite.
What the trail doesn't show
No captures mention guard clauses, early returns, error wrapping conventions, or naming patterns. These are the things that happen on autopilot — too obvious to record as decisions because they were never questioned. The absence is itself data: it maps the boundary between deliberate choices and internalized defaults.
The uroboro decision trail captures what was contested, not what was assumed. A complete style profile would need both — the conscious decisions from the trail plus the unconscious patterns from git diffs. That's what the distill command's correlation feature is designed to bridge.