Change Shape
Change boundaries: what belongs together, what should split, and how much work one review should carry.
68 items in this guidance cluster.
Tagged guidance
Guide items
Code Shapecode-shapeCode-shape guidance covers small source-level moves that reduce live context, improve reader locality, and keep structure changes reviewable. It focuses on local expression shape, cohesion, coupling, reversible structure, and separating behavior from preparation.JJ Workflowjj-workflowJJ workflow guidance covers source-control inspection, reviewable changes, descriptions, bookmarks, publication, and recovery in jujutsu repositories. It keeps agents and maintainers thinking in jj changes and operations instead of Git-shaped habits.Software Change Preferencessoftware-change-preferencesSoftware-change guidance covers broad preferences for change size, structure, validation, review artifacts, commit history, and handoff. It favors small coherent changes, explicit tradeoffs, and evidence matched to the changed surface.
Agent Workflow rules
Isolate Workspaces by TaskAGENT-ISOLATE-WORKSPACES-BY-TASKPut separable or parallel agent work in its own workspace or source-control lane. Isolation keeps diffs, validation, and ownership clear when multiple changes are in flight.Prefer Build-Preserving EditsAGENT-PREFER-BUILD-PRESERVING-EDITSMake multi-step edits in slices that keep compilation or tests close to green when the route allows it. Build-preserving work keeps failures close to the edit that caused them.Present Concrete Next OptionsAGENT-PRESENT-CONCRETE-NEXT-OPTIONSAfter a validated chunk, offer specific follow-up chunks with their tradeoffs. Concrete options let the maintainer steer scope without decoding vague requests to continue.Preserve Human WorkAGENT-PRESERVE-HUMAN-WORKInspect and protect unrelated local edits before changing files. Preserving human work keeps the task diff focused and avoids destroying unfinished or intentional changes.Separate Notes From CorrectionsAGENT-SEPARATE-NOTES-FROM-CORRECTIONSCapture fast-review notes before fixing them when there are multiple comments or unclear patterns. Separating capture from correction preserves signal and supports coherent follow-up.
Change Shape rules
Avoid Speculative Public APICHANGE-AVOID-SPECULATIVE-PUBLIC-APIAdd public surfaces only when current or accepted callers need them. Waiting for concrete pressure keeps compatibility commitments smaller and easier to validate.Avoid Unnecessary Dependency ChurnCHANGE-AVOID-UNNECESSARY-DEPENDENCY-CHURNKeep package, manifest, and lockfile movement out of unrelated work. Separate dependency changes make build, compatibility, and downstream risk reviewable on their own.Identify Owning Module Before EditingCHANGE-IDENTIFY-OWNING-MODULE-BEFORE-EDITINGFind the component that owns the concept before adding or moving logic. That keeps invariants, tests, and future maintenance close to the responsible code.Isolate Controversial ChangesCHANGE-ISOLATE-CONTROVERSIAL-CHANGESPut risky or contentious moves in their own review unit when they can stand alone. This lets reviewers approve, reject, or revise the decision without incidental cleanup attached.Minimal but CompleteCHANGE-MINIMAL-BUT-COMPLETEKeep the diff as small as the purpose allows while including the evidence that purpose needs. Reviewers should see one coherent unit they can understand, validate, and revert.Pin Behavior With Early TestsCHANGE-PIN-BEHAVIOR-WITH-EARLY-TESTSAdd characterization tests before changing messy behavior when the existing contract is unclear. The baseline separates intentional behavior changes from accidental drift.Prefer Small Follow-UpsCHANGE-PREFER-SMALL-FOLLOW-UPSMove adjacent cleanup or broader improvements into focused follow-up changes when the current diff can stand alone. This preserves review focus while still capturing useful work.Preserve Unowned WorkCHANGE-PRESERVE-UNOWNED-WORKTreat nearby edits from users, agents, generators, or earlier changes as outside your ownership unless the task says otherwise. Adapting around them protects parallel work and context.Respect Generated Artifact OwnershipCHANGE-RESPECT-GENERATED-ARTIFACT-OWNERSHIPFix generated outputs through their source inputs, templates, metadata, or generator configuration whenever those own the result. Hand edits are durable only when the tool workflow explicitly supports curation.Separate Structure From BehaviorCHANGE-SEPARATE-STRUCTURE-FROM-BEHAVIORSplit refactoring or layout changes from behavior changes when the combined diff obscures intent. Separate review units make meaning preservation and new behavior easier to check.Sync Generated ArtifactsCHANGE-SYNC-GENERATED-ARTIFACTSUpdate checked-in generated outputs when their source inputs change and they are part of review. Keeping them aligned prevents consumers from seeing stale artifacts.Treat And as Scope WarningCHANGE-TREAT-AND-AS-SCOPE-WARNINGUse compound change descriptions as a prompt to inspect whether the work has more than one purpose. The word is not a rule, but it catches scope creep while splitting is still cheap.Use One Purpose per ChangeCHANGE-USE-ONE-PURPOSE-PER-CHANGEShape each change around one review question and one reason for existing. Related tests, docs, and generated files can travel with it when they support that same purpose.
Performance rules
Justify Complexity, Churn, and DependenciesPERF-JUSTIFY-COMPLEXITY-CHURN-AND-DEPENDENCIESExplain why a performance win justifies added complexity, churn, unsafe code, caching, or dependencies. Measured speedups still need to pay for the maintenance cost every future reader inherits.Optimize Measured HotspotsPERF-OPTIMIZE-MEASURED-HOTSPOTSOptimize code that measurement shows is on the important runtime path. This keeps review attention on changes whose user-visible impact justifies altering the code shape.
Refactoring rules
Align Seams with Real VariationREFACTORING-ALIGN-SEAMS-WITH-REAL-VARIATIONPut abstraction seams where code already varies across backends, policies, protocols, tests, or ownership boundaries. Avoid adding names and jumps for hypothetical futures unless the next change or risk clearly justifies them.Do Not Over-apply DRYREFACTORING-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 HelpersREFACTORING-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 VisibleREFACTORING-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 CloseREFACTORING-KEEP-WEAK-ABSTRACTIONS-CLOSE-TO-THEIR-USEKeep 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.Prefer Local ReasoningREFACTORING-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 EffectsREFACTORING-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 ParagraphsREFACTORING-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
Classify Prototype ReuseREVIEW-CLASSIFY-PROTOTYPE-REUSEClassify whether a rebuild is reusing behavior, evidence, replaceable internal shape, or load-bearing boundaries. That separation helps preserve proven compatibility while discarding prototype scaffolding.Define Slices in IssuesREVIEW-DEFINE-SLICES-IN-ISSUESShape issues around review-sized slices with clear outcomes. Coherent slices reduce scope creep and give maintainers or agents a practical unit of work without losing the larger purpose.Separate Discovery, Selection, and ImplementationREVIEW-SEPARATE-DISCOVERY-SELECTION-IMPLEMENTATIONSplit problem discovery, solution selection, and implementation review when they require different decisions. This keeps design debate out of patch correctness review once scope or direction is still unsettled.
Rust rules
Avoid Empty Wrapper TypesRUST-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.Consider Downstream API ImpactRUST-CONSIDER-DOWNSTREAM-API-IMPACTCheck public API changes against downstream imports, traits, inference, and examples before reshaping them. Additive paths and deprecations often avoid unnecessary breakage.Keep Crate Boundaries NarrowRUST-KEEP-CRATE-BOUNDARIES-NARROWPut behavior and tests in the crate or module that owns them before extracting shared helpers. Narrow boundaries reduce dependency fan-out, feature pressure, and hidden coupling.Keep Dependency Updates IntentionalRUST-KEEP-DEPENDENCY-UPDATES-INTENTIONALSeparate maintenance-only dependency refreshes from updates that change behavior, features, MSRV, or integration. Reviewable grouping lowers noise without hiding downstream risk.Keep Edits Scoped to Owning ConceptRUST-KEEP-EDITS-SCOPED-TO-OWNING-CONCEPTChange the module, crate, feature, or facade that owns the behavior being fixed. Scoped edits keep reviews atomic and prevent nearby files from pulling in unrelated concepts.Keep Pre-Release Compatibility IntentionalRUST-KEEP-PRE-RELEASE-COMPATIBILITY-INTENTIONALPreserve pre-release compatibility only when it reflects a chosen contract. Early cleanup is often cheaper than freezing accidental names, re-exports, features, or variants.Keep Public API Shape IntentionalRUST-KEEP-PUBLIC-API-SHAPE-INTENTIONALMake public visibility, aliases, features, re-exports, bounds, and variants reflect intended commitments. Published surface area becomes something downstream users can depend on.Use Functions For Incidental TypesRUST-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.
Testing rules
VCS rules
Create an Operation Log Point Before ReshapingVCS-CREATE-OPERATION-LOG-POINT-BEFORE-RESHAPINGCreate a recent jj operation boundary before risky stack reshaping. Recovery is easier when there is a known point before rebases, splits, squashes, or repairs.Duplicate for Alternative CandidatesVCS-DUPLICATE-FOR-ALTERNATIVE-CANDIDATESUse jj duplicate when two plausible fixes or refactors need independent validation. Separate candidate changes preserve comparison and recovery without mutating the only option.Inspect State Before MutatingVCS-INSPECT-STATE-BEFORE-MUTATINGInspect working-copy, stack, bookmark, conflict, and unowned state before mutation. Current state keeps edits scoped and avoids rewriting work the agent did not inspect.JJ New for Review LanesVCS-JJ-NEW-FOR-REVIEW-LANESStart unrelated review units with jj new before edits accumulate. Separate changes keep review atomic while leaving later squash or absorb decisions easy.Workspace Add for Second CheckoutsVCS-WORKSPACE-ADD-FOR-SECOND-CHECKOUTSUse jj workspace add only when a task needs another filesystem checkout. Ordinary review separation should use jj new; workspaces fit clean validation or parallelism.
Pattern items
Cap Change Radiuscap-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 Statementschunk-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.Follow Local Conventionsfollow-local-conventionsInconsistent style and structure make each change feel like a new design decision. Start from nearby patterns and only diverge when the local convention cannot support the current need.Keep Public Dependencies Intentionalkeep-public-dependencies-intentionalPublic dependencies shape downstream compatibility, API expectations, and maintenance cost. Add or raise them only when the public behavior needs that requirement, using lockfile updates for ordinary compatible refreshes.Keep Structure Reversiblekeep-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.Make The Change Easy Firstmake-the-change-easy-firstSome changes are risky because the path to make or verify them is unnecessarily hard. First add the smallest harness, boundary, helper, tool, or runbook that makes the real change cheaper to understand and review.Move Declaration And Initialization Togethermove-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 Couplingname-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 Long Term Coherenceoptimize-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.Preserve Unowned Workpreserve-unowned-workShared working copies may contain edits from another person or an earlier task. Check state before editing, work around unrelated changes, and stop for direction when unowned work blocks the current change.Reader Localityreader-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.Separate Discovery From Editingseparate-discovery-from-editingEditing while still discovering the system can bake early misunderstandings into the diff. Read enough to find the ownership, constraints, and likely change shape before making scoped edits.Separate Structure From Behaviorseparate-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.Small Reviewable Chunkssmall-reviewable-chunksLarge mixed changes blur structure, wording, behavior, and workflow decisions until review becomes slow or shallow. Choose one coherent purpose per chunk, validate it, and ask for direction before expanding into preference-sensitive follow-up work.Strengthen Cohesionstrengthen-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 Changinguntangle-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 Variableuse-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 Clauseuse-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 items
Change Shape Controls Review Costchange-shape-controls-review-costChange boundaries determine how much intent, risk, validation, and revert cost a reviewer must reconstruct. Use the smallest coherent unit that preserves trust without splitting one decision into noise.Reader Locality Reduces Change Costreader-locality-reduces-change-costCode is cheaper to change when the reader can understand the local decision without distant facts. Keep related state, inputs, side effects, and policy close enough to inspect together.