Software Change Preferences

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

Core Preference

Prefer changes that reduce reader burden while preserving behavior. A good change makes the important concept, boundary, or rule easier to see from the code and easier to verify from the handoff.

Optimize for:

  • Local reasoning over distant reconstruction.
  • Observable behavior over private implementation shape.
  • Small reviewable chunks over broad mixed diffs.
  • Explicit tradeoffs over unspoken cleverness.
  • Honest verification over implied confidence.

Change Shape

Start by identifying the smallest coherent unit that can be reviewed on its own. A chunk can be a structure-preserving refactor, a behavior change, a documentation update, or a pattern entry, but it should not mix unrelated decisions.

Scope

Keep scope narrow enough that a reviewer can name the change's purpose without reconstructing the whole branch:

  • Use one feature, bug fix, or documentation purpose per change.
  • Do not include unrelated refactors.
  • Do not include dependency churn unless it is necessary for the task.
  • Do not commit binary artifacts; use Git LFS, release assets, PR uploads, CI artifacts, or external storage for large opaque outputs.
  • Do not move broad modules unless the reader path improves.
  • Do not add speculative public API for future features.

Use Avoid Speculative Public API when a change wants to expose names, types, or extension points before the current need is real.

Use Use One Purpose Per Change, Avoid Unnecessary Dependency Churn, and Keep Binaries Out Of Source Control when scope pressure would mix unrelated work or opaque artifacts into the same review.

Follow-Ups And Generated Output

When a change reveals separate cleanup, note it or put it in a separate change rather than widening the current diff. Keep generated artifacts in sync when they are part of the review surface, but edit the durable source instead of generated output when release tooling owns the generated artifact. Use Respect Generated Artifact Ownership when the durable fix belongs in the source input, template, generator config, or release metadata.

Use Small Reviewable Chunks when a change could grow into multiple review concerns. When structure and behavior can be separated cleanly, land the structure change first and verify it before changing behavior. Use Code Shape when the main decision is how to reduce live context, limit change radius, preserve reversibility, or clarify cohesion and coupling. Use Prefer Small Follow Ups, Sync Generated Artifacts, and Separate Structure From Behavior when follow-up work, generated output, or refactoring boundaries affect review shape.

Local Context

Read the repo before applying general preferences. Local instructions, existing helpers, naming schemes, tests, and version-control workflow usually contain information that a general guide cannot know.

Ownership

Before editing, identify the owning module, the adjacent modules it depends on, and the test style already used for the behavior. That local map keeps a general preference from overriding the shape the codebase already uses.

Use Identify Owning Module Before Editing before changing code whose local owner, neighbors, or test style are not yet clear.

Local Fit

Prefer the existing style when it is coherent. If the existing shape is actively making the change harder to understand, improve the local structure, but keep that improvement scoped to the same concept.

Use Follow Local Conventions when general guidance and project shape might conflict. Use Separate Discovery From Editing when the local shape is not clear enough to edit confidently.

Working Copy Care

Assume unowned edits belong to someone. Do not revert, rewrite, or absorb work just because it makes the current diff look cleaner.

Use Preserve Unowned Work when a shared working copy has pre-existing edits or changes appear while work is in progress. Use Change Preserve Unowned Work when this needs compact change-shape rule wording.

Verification

Choose verification by the risk of the change. Formatting changes need formatting checks, signature changes need type or build checks, behavior changes need tests or smoke checks that exercise the changed path.

Change-Specific Proof

Choose validation by starting with the narrowest useful command before editing, then widening proof as the risk of the change grows:

  • Run focused tests for touched behavior.
  • Run the project gate when practical.
  • Run Markdown linting for Markdown-only or doc-heavy changes.
  • Report validation gaps directly.

Use Choose Validation By Risk and Run Fast Format And Lint Gates Early when selecting the first useful check for a change.

Generated And Visible Output

Validate changes against the surface users receive, not only the source that generated it:

  • Validate template changes against generated output, not only the template source.
  • Regenerate affected reference projects when templates change.
  • Run checks inside generated projects when generated projects are what users receive.
  • Smoke-test interactive flows when event loops, terminal setup, or terminal teardown changed.
  • Attach screenshots, GIFs, or before/after context when visible UI output changed.
  • Document manual verification when CLI or TUI behavior lacks automated coverage.

Use Match Evidence To Surface when template, generated-project, CLI, TUI, rendered, parser, public API, or performance changes need proof from the surface users receive. Use Prove Command Construction And Display, Cover Navigation Boundaries, and Run Docs As First Class Gate when command output, terminal navigation, or docs are the user-visible surface.

For optimization work, use one change per optimization idea. Record the hypothesis and expected mechanism before touching hot code, run correctness before timing, and keep failed ideas useful by recording why the evidence did not support them.

Do not make keep/revert decisions from one short benchmark run. Use increasingly expensive evidence only when the previous step justifies it: counters, phase timers, per-case rows, hot-function maps, microbenchmarks, profilers, and assembly inspection. Record exact commands, versions, hashes, environment, corpus, raw samples, and interpretation for benchmark results worth comparing later.

Never run benchmarks in parallel when timing data matters.

Use Measure Goal Change Compare, Run Correctness First, Avoid Single Run Conclusions, Record Benchmark Provenance, and Run Timing Benchmarks Sequentially when optimization work affects review shape or validation cost.

Use Smallest Trustworthy Verification to choose the cheapest credible check. Use Report Verification Honestly to distinguish what ran, what failed, and what was not checked.

Review Artifacts

Use issues for review-sized slices. Each issue should include the problem, scope, out-of-scope work, behavior references, and acceptance criteria. Use Define Slices In Issues when the issue itself needs to make a future review unit clear.

Issues And Discussion

For non-obvious work, start with an issue before opening the review change. Use the issue to discuss use cases, constraints, requirements, prior art, solution tradeoffs, and maintenance load before the patch asks reviewers to judge implementation details. Do not mix problem discovery, solution selection, and implementation review when they need separate decisions. Use Separate Discovery Selection Implementation when the problem, design choice, and patch correctness need different review artifacts.

When a discussion is long, summarize it for reviewer decisions. Avoid low-signal status comments: if there is a status change, update the issue, PR checklist, handoff, or other source of truth instead of nudging reviewers. Use Update Source Of Truth when an issue, PR, checklist, or handoff should own the current state.

Treat review as a two-way discussion. When a reviewer asks about intent, tradeoffs, risk, behavior, API shape, or alternatives, answer the question instead of only pushing new code; use Answer Questions Before Code for that review pattern. Leave review threads unresolved for the reviewer unless the resolution is unambiguous, and use Let Reviewers Resolve Threads when comment ownership affects review clarity.

Plans

Use implementation plans for multi-phase work. A useful plan records current state, desired end state, non-goals, approach, phases, automated verification, and manual verification. Use Make Plans Versioned Artifacts when a plan needs review, history, or resumption outside the chat thread.

Prototype Rebuilds

When rebuilding from a prototype or prior implementation, classify what is being reused: externally visible behavior, evidence, replaceable shape, or load-bearing boundary.

Treat names, helper placement, crate boundaries, and document shape as replaceable unless they carry a domain constraint.

Discuss load-bearing boundaries before replacing them. A smaller local API is not automatically better if it centralizes an open-ended domain or removes room for independent growth.

Record prototype boundary review in the issue, PR notes, or ADR when the implementation depends on earlier work.

Use Classify Prototype Reuse when a rebuild depends on behavior, evidence, or boundaries discovered in a prototype.

PR Narrative

Use PR descriptions or review packets to explain the summary, design notes, user-facing surface, tests or validation, reference material, and follow-up.

For code changes that need technical narration, include the problem, mental model, non-goals, tradeoffs, architecture impact, observability impact, validation, and documentation deltas. Describe behavior and intent rather than walking through the diff line by line.

Label speculation as inferred or unknown. Link critical claims to evidence such as tests, call sites, runtime behavior, source documentation, or generated artifacts.

Use Explain PR Problem Model And Proof, Preserve Durable Answers Near Source, Label Speculation As Inferred Or Unknown, and Make Review Artifacts Standalone when review narrative needs to preserve reasoning for readers who did not see the discussion.

PR descriptions should name the generated surface that changed: generated samples should state which generation commands ran, templates should state which templates changed, and feature-flag changes should name the affected features.

Durable Decisions

Use ADRs for durable decisions. Reach for them when a decision changes package boundaries, ownership boundaries, parser architecture, policy, registry purpose, release scope, or another long-lived shape.

Use ADRs when changing a load-bearing boundary that future changes will have to route through.

Use Use ADRs For Boundaries And Ownership when a decision changes long-lived ownership, policy, parser, package, or registry shape.

Commit History

Commit messages and jj descriptions are part of the change. They should help future readers understand why the change exists and what decision it captured.

Atomicity

A change is atomic when it can stand on its own: it fulfills one purpose, is minimal but complete, and builds, formats, and passes its relevant tests when considered separately. Watch for scope warnings such as and in the change description, dead code inside the diff, or fix-up changes after CI or review that show the original change was not complete.

Use Minimal But Complete, Treat And As Scope Warning, and Use One Purpose Per Change when shaping a change that needs to stand on its own.

Review Path

Shape the review path so the important behavior change is easy to follow. Early test changes can pin existing behavior before the patch changes it, and small refactor changes can act as guideposts through a larger behavior change. Split refactors from behavior changes when the combined diff would force reviewers to reverse engineer what changed, make each change's intent visible in its summary, and isolate controversial changes so review attention does not starve unrelated work. Avoid dependency changes that only make sense if a later controversial change lands.

Use Commit Messages For History when setting jj descriptions or preparing published commits. Follow the repository's commit convention; use Conventional Commits only where the repo has already adopted that spec. Use Pin Behavior With Early Tests and Isolate Controversial Changes when the review path needs guidepost tests or a separate lane for a risky decision.

Review Questions

Review Change Shape

  • Does this change have one coherent purpose?
  • Did it reduce what a reader must remember?
  • Did it preserve behavior or name the behavior change clearly?
  • Did it follow local project conventions before general preference?
  • Did it avoid overwriting unowned work?

Review Verification

  • Did verification target the likely failure?
  • For performance work, did correctness run before timing and did benchmark evidence include enough provenance to compare later?
  • Does the handoff say what actually ran?

Review Artifact

  • Does the review artifact name scope, non-scope, evidence, and follow-up?
  • Does the review artifact explain the mental model, architecture impact, observability impact, and documentation delta when those changed?
  • If this comes from a prototype, did the review separate behavior, evidence, replaceable shape, and load-bearing boundaries?