Reader locality

Definitions, decisions, and use sites kept near enough that a change does not require a repository tour.

91 items in this guidance cluster.

Tagged guidance

Guide items

Agent workflow rules

Boundary rules

Change shape rules

Documentation rules

Avoid generated prose tellsReplace templated, UI-centered, or polished-but-vague phrasing with concrete behavior. Keep the local voice trustworthy without cutting useful explanation.Choose document typePick the dominant document mode before editing so the page serves one reader task well. Link out to secondary modes instead of blending tutorial, reference, decisions, and changelog.Front-Load useful pointPut the decision, command, invariant, or warning before broad setup. Readers and agents can then use the page without hunting through introductory prose.Group related list itemsCluster long lists under useful names when the relationships matter. Keep short or causal material flat or in prose so structure does not add noise.Hide catalog mechanicsLead user-facing copy with work areas, artifacts, and destinations instead of IDs or generated structure. Mention catalog mechanics only when citation or contribution work needs them.Match page shape to reader taskShape pages around the readers task, such as learning, choosing, reference, or review. The right structure lowers scan cost without forcing one page to do every job.Name destination, not directionUse labels that name the section, object, or decision the reader will reach. Directional labels make readers follow the page order before knowing whether it is relevant.One dominant mode per pageLet each page have one primary mode and move competing material behind links. This keeps readers from paying for tutorial, reference, explanation, and policy at once.Own AI-assisted proseAI-generated or AI-assisted docs are reasonable to share when human curation makes them author-owned. The published artifact should carry checked claims, reader-sized scope, relevant evidence, real tradeoffs, and local voice.Prose for relationships, lists for enumerationUse prose when causality, contrast, or priority matters, and lists when enumerating parallel items. The shape should reveal the relationship instead of hiding it in bullets.README as entry pointUse README files to orient readers to purpose, setup, first useful use, and deeper docs. Split out manual-level detail when it hides the starting path.Separate technique from example policyTraining examples should distinguish the library or framework technique being taught from application-specific policy. Explain the policys rationale, tradeoffs, and meaningful edge cases, then tell readers what to reuse and what to reconsider.Use concrete detailsName real commands, paths, defaults, types, examples, and work areas when they clarify scope. Concrete detail removes guesswork without overloading prose with incidental facts.Use descriptive headingsWrite headings that name the section content, destination, or decision area. Reserve imperative headings for procedures where the section is truly a step.Write for non-linear readersGive sections enough local context to work when reached from search, links, review, or retrieval. Avoid repeating the whole introduction; add only the subject and prerequisite needed.Write technical proseUse direct technical language that carries contracts, commands, evidence, and tradeoffs. Cut marketing, coaching, chat, and page narration when they do not explain the system.

Refactoring rules

Do not over-apply DRYKeep similar-looking code separate until it has the same meaning and changes together. Premature sharing can couple unrelated policies and make later edits harder.Extract concept helpersExtract helpers when the new function names a real concept boundary with a stable purpose. Hiding a few lines behind a weak name adds a jump without reducing the readers burden.Keep linear story visibleKeep simple ordered workflows inline when the sequence is the clearest explanation. Extract only the substeps that carry their own concept, policy, reuse, or test surface.Keep weak abstractions closeKeep tentative helpers, types, or traits near their first use until the boundary proves itself. Local placement makes weak abstractions easier to revise, inline, or delete before other modules depend on them.Make edge cases explicitName boundary behavior near the branch, calculation, or return that depends on it. This makes policy reviewable and shows when stronger types should prevent invalid states instead.Prefer local reasoningShape code so relevant state, invariants, and effects are visible near the change. Centralize only when it reduces total reasoning, because distant reconstruction raises cognitive load and error risk.Prefer loops for side effectsUse ordinary loops when the main purpose is mutation, I/O, logging, or other side effects. Iterator chains are better for value transformation; using them for effects can hide order, early exits, and error handling.Use whitespace as function paragraphsUse blank lines to group related statements inside a function before extracting more names. Paragraph-like spacing can reveal the local story while avoiding unnecessary helper jumps.

Review rules

Rust rules

Avoid broad context and callbacksPass explicit inputs and keep control flow local instead of hiding it in context bags or callbacks. This makes ownership, effects, and ordering easier to audit.Avoid empty wrapper typesAdd a wrapper type only when it carries an invariant, behavior, or ownership boundary. Otherwise it adds conversions and concepts without improving correctness.Avoid giant crate rootsUse the crate root to teach the public shape and route readers to focused modules. This keeps lib.rs or main.rs from becoming the whole implementation surface.Avoid inline modulesPut nontrivial modules in named files unless tests, preludes, or generated code justify inline layout. Stable paths make search, review, and ownership clearer.Avoid mod.rs by defaultPrefer named module files when they make tabs, paths, and search results clearer. Reserve mod.rs for cases where local convention or layout makes it the better signal.Avoid overcommenting trivial codeComment Rust code for invariants, contracts, and surprising tradeoffs rather than restating obvious operations. This keeps comments useful and less prone to drift.Avoid path attributesUse normal Rust module lookup unless generated or platform-specific layout needs #[path]. Predictable file paths make navigation and ownership easier to infer.Avoid tiny module mazesKeep small helper code near its use unless a separate module owns a real concept. This reduces file-jumping and preserves reader locality.Central item firstPut the main type, trait, enum, or function before supporting details. Readers can learn the modules purpose before chasing helpers and adapters.Choose generics and trait objects deliberatelyPick generics, stored type parameters, or trait objects for the variation they actually model. The choice affects compile cost, object safety, lifetimes, and caller ergonomics.Expose primary path from crate rootMake the crate root show the main workflow, types, and import path. Users should not have to infer the intended entry point from private layout details.Group module importsGroup related imports by module when that matches local style. This makes dependency shape easier to scan and avoids churn from one-import-per-line edits.Group private imports before public re-exportsSeparate implementation imports from public re-exports in module prologues. The grouping lets readers distinguish internal dependencies from the API surface being presented.Keep concepts coherentGive each module, type, or helper one recognizable idea to own. Coherent ownership keeps readers from carrying unrelated parsing, state, rendering, and policy facts at once.Keep preludes re-export onlyPut only re-exports in prelude modules and keep original behavior in its owning module. Users expect preludes to aid imports, not hide implementation ownership.Make public API browseable from layoutAlign public modules, re-exports, and source files so readers can navigate from API to ownership without translation. Facades are fine when they improve discovery and still point toward the owning concept.Make side effects explicitPut mutation, I/O, registration, cleanup, and background work in names, call sites, or docs when callers must account for them. Keep tiny private helpers plain when the surrounding code already makes the effect obvious.Name auditable intermediatesIntroduce named locals where parsing, validation, rendering, ownership, or side-effect decisions need review. Avoid naming every trivial expression when it would add ceremony without clarifying the boundary.Order code for readingArrange code so central items, callers, or public API appear before supporting helpers when that makes the file readable top to bottom. Prefer the order that reduces reader jumping over mechanical rearrangement.Order items for API readingOrder imports, public items, impls, trait impls, and helpers so the API story is easy to scan. Respect macros, generated code, and local convention when another order communicates better.Prefer boring direct codePrefer explicit Rust control flow, types, and error handling over clever framework-shaped indirection. Use macros or abstractions when they remove real repetition or enforce real invariants.Prefer concept owned modules and named filesOrganize modules around domain concepts and give important concepts named files that own their types, invariants, tests, and docs. Use infrastructure modules only when the cross-cutting concept is real and bounded.Prefer small clear shapesFavor small functions, narrow structs, and simple enums that keep live facts local for readers. Do not split cohesive logic into fragments that force more navigation than understanding.Reexport for discoveryRe-export public items where callers naturally look so the crate surface is discoverable without hiding ownership. Keep canonical definitions and docs clear so re-exports do not become competing homes.Review as future maintainerReview Rust changes for the reader who will debug, extend, or release the code later, not only for immediate correctness. Favor maintainable API shape, docs, tests, and error behavior over changes that merely compile.Shape expressions for auditabilityShape complex expressions so ownership, validation, error handling, and side effects can be audited at the point they occur. Break chains or introduce names when density hides a decision readers must verify.Use directory modules as tables of contentsLet directory module files introduce, organize, and re-export the concepts owned by that directory. Keep substantial implementation in named child files so the module remains a readable table of contents.Use doc inline for canonical reexportsUse #[doc(inline)] when a re-export should be the canonical place readers encounter an item. Avoid inlining re-exports that would obscure the owning module or create duplicate-looking documentation.Use field init shorthandUse field init shorthand when variable names already match struct fields so initialization stays compact and familiar. Spell fields out when renaming, conversion, or policy deserves visible attention.Use functions for incidental typesPrefer free or module functions when a type does not own the operation or invariant. Move behavior onto a type when the method relationship clarifies state, policy, or trait design.Use meaningful standard typesPrefer standard or ecosystem types that encode ownership, units, paths, durations, optionality, and invariants better than raw strings or integers. Use domain newtypes when the standard type cannot prevent meaningful mixups.

Testing rules

Pattern items

Avoid boolean flag parametersBehavioral boolean flags make call sites depend on hidden ordering and branch semantics. Distinguish them from boolean domain data, then prefer named operations, enums, options types, or builders when the caller selects behavior.Cap change radiusBroad diffs increase review cost and make unrelated regressions harder to isolate. Keep the change radius aligned with the requested behavior, using separate chunks for cleanup or adjacent improvements.Chunk statementsDense prose asks readers to hold too many claims at once and hides which idea needs review. Split statements into coherent chunks so each paragraph, bullet, or sentence carries one inspectable purpose.Delete redundant commentsComments that repeat obvious code add reading burden and become stale faster than the behavior they describe. Remove them or replace them with context that explains intent, invariant, risk, or non-obvious tradeoff.Keep name currentNames that preserve old intent make readers distrust the code or documentation around them. Rename when the concept changes enough that the old name now teaches the wrong model.Keep structure reversibleEarly structure can harden into unnecessary abstraction before the design is proven. Prefer arrangements that are easy to inline, split, merge, or rename until the underlying concept earns permanence.Limit live contextReaders make mistakes when they must keep too many facts active to understand a change. Reduce live context by moving related facts together, naming intermediate concepts, and keeping dependencies local.Make parameters explicitHidden configuration, time, randomness, globals, or environment reads make behavior hard to reason about and test. Gather ambient data at the outer boundary, then pass typed inputs or a cohesive context to the inner operation.Make state transitions explicitLifecycle rules become fragile when status fields, timestamps, events, and validation checks are coordinated by hand. Give meaningful transitions a named owner that holds the preconditions, state update, event, and error behavior together.Move declaration and initialization togetherA value declared before it is valid makes readers track an empty slot and its future assignment. Declare values where they become meaningful, using immutable locals and narrow scopes unless evaluation order requires more care.Name couplingRelationships between pieces are hard to judge when the reason they change together is unnamed. Describe the change pressure first, then decide whether the coupling belongs directly, behind a clearer owner, or across an explicit boundary.Optimize for agent legibilityRepositories that are hard for agents to inspect, search, run, and validate make delegated work slower and less reliable. Prefer structures, commands, names, examples, and runtime signals that help both agents and human maintainers reason locally.Optimize for long term coherenceAgent-produced work can satisfy a prompt while weakening the systems future concepts, names, boundaries, and tests. Choose the smallest change that preserves long-term direction without using coherence as an excuse for speculative architecture.Reader localityA change can reduce code size while increasing the number of jumps needed to understand one workflow. Keep related concepts near their meaning, extracting only when the new name and location reduce live context.Run source explanation passTurn a source tree into a self-contained reading environment by recovering its mental models, fundamentals, decisions, constraints, and edge cases. Establish the system map before item detail, audit every relevant helper and path, and measure success through reader comprehension rather than comment count.Separate structure from behaviorDiffs that mix moves, renames, formatting, and behavior make review and rollback harder. Separate behavior-preserving structure from rule changes when each can be checked on its own.Strengthen cohesionA concept becomes harder to understand when its data, rules, and behavior are scattered or bundled with unrelated concerns. Move elements that change for the same reason toward one named owner, while separating nearby code that belongs to another concept.Untangle before changingBehavior changes become risky when policy, formatting, validation, persistence, and side effects are braided together. Untangle only enough structure to give the new behavior a clear owner, then keep the behavior change reviewable.Use explaining variableImportant decisions disappear when nested expressions or repeated conditions expose syntax before domain meaning. Introduce a local name when it makes the next branch, call, or return read in terms of the fact the reader needs.Use guard clauseThe normal path is harder to see when the rest of a routine is indented under a precondition or failure case. Exit early for boring gates so the ordinary behavior stays flat, visible, and ordered by what readers must rule out.

Principle item

Mechanism item

Agent item