← Back to Distilling style

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.

Captures
534
90 days
Decisions
~50
explicit X-over-Y
Projects
9
personal + work
Themes
8
recurring patterns

Dependency avoidance

highest frequency

The 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.

Regex-based link extraction over golang.org/x/net/html
Avoids adding external dependency for a simple task. Only need to find href attributes on same-domain links.
slopsquid
Static banlists + frequency-ratio scoring over local LLM approach
v1 should be fast and dependency-free. Paper's empirical data provides quantitative scoring without needing inference.
slopsquid
In-memory queue over Bull/BullMQ with Redis
Single-process NestJS app, no Redis dependency needed, queue state is transient, simpler to implement and debug.
rpa-api
Single HTML with inlined CSS/JS over multi-file structure
Matches existing patterns — all projects are self-contained 8–50KB HTML files with no external dependencies.
qryzone /fun/
Rule

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-project

A 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.

Single click counter over level+count state
Derive visual quadtree from total clicks. Growth is linear accumulation — the tree was over-engineered for what was actually a simple binary accumulation pattern.
qryzone /fun/
PortalSessionState map over separate VLM/Traces fields
Unified getOrCreateSession with portal param. Eliminates copy-paste duplication (6 fields, 6 methods), creation-promise lock fixes race condition.
rpa-api
Stateless BrowserService (pass page as param) over mutable this.page
Eliminates concurrency bugs when VLM and Traces queues drain simultaneously on the singleton BrowserService.
rpa-api
Rule

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

contextual

When 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.

Extract createPersistentSession helper over duplicating getOrCreatePersistentSession
VLM and Traces sessions follow identical patterns. Extracting avoids copy-paste and makes the dual-session pattern maintainable.
rpa-api
Extract hasRootCauseContent to shared utility over inline function in route file
Enables reuse if internal CAPA flow needs validation, keeps domain logic near domain types.
webapp-ui

But the opposite also happens:

Duplicate parseTimestamp in mcp.go over extracting to shared package
Function is small, keeps MCP layer self-contained. Extraction would create a cross-layer dependency for a trivial function.
uroboro
Rule

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

repeated

Multiple captures record discovering that a clean abstraction doesn't work with the actual framework, and choosing the pragmatic workaround over fighting the system.

Revert fun-base.njk template over Nunjucks block inheritance
Nunjucks block inheritance doesn't work with Eleventy's layout: frontmatter system. Blocks render empty.
qryzone
extraStyles frontmatter over Nunjucks blocks
Pages use layout frontmatter pattern, not extends/blocks. Adding extraStyles to base template keeps consistency with existing pattern.
qryzone
HTML format over Markdown
Task spec said markdown/Astro but site is actually Eleventy with all content as .html files with Nunjucks frontmatter. Matching existing format.
qryzone
Rule

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

philosophical

A recurring willingness to ship with known limitations rather than block on unavailable perfect data. The imprecision is always documented.

Estimated overuse ratios over wait for measured data
Without actual 67-model frequency data for technical writing, used heuristic weights. Still produces meaningful relative scoring. Article explicitly notes this limitation.
slopsquid
Use antislop paper data tables over running auto-antislop tool
The tool is designed for inference-time suppression during LLM generation (requires GPU + vLLM). For editing existing text, the paper's empirical data provides everything needed.
slopsquid
Rewrite docs to match actual codebase over keeping aspirational features
Previous docs described unrealized features. Replaced with accurate documentation of the three commands that actually exist. Only document what exists.
slopsquid
Rule

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-directional

Regex 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.

Broadened not_x_but_y regex — any subject + period separator
Original regex only matched it/this/that subjects and comma/dash separators. User's content uses varied subjects and period boundaries.
slopsquid
Require negation in not_x_but_y — tightened after false positives
Original regex made "not" optional, causing false positives on normal "it's X, but Y" English. Fixed to require "isn't/wasn't" forms explicitly.
slopsquid
Rule

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

testing

Testing decisions consistently prefer real system interaction over mocked substitutes, and implementation sequencing is chosen to unblock testability early.

Auth state persistence over HTML mocks
Mock can drift from reality, causing "works in test, fails in prod" scenarios.
rpa-api
Form filling before auth/nav — sequenced for early testing
Allows testing on live form immediately via CDP. Auth implementation can follow without blocking test feedback.
rpa-api
Rule

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 clear

Rewriting from scratch is not the default. But when architectures are genuinely incompatible, incremental migration creates more adapter code than the rewrite would produce.

Clean rewrite over incremental migration
The old code is a TUI RSS reader with incompatible schema, CGO sqlite, and Bubble Tea dependencies. The new architecture is fundamentally different.
osmotic
Rule

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.