# Notes

## Precedence

- The rules in user-editable AGENTS files take priority over any conflicting
  rule from non-user-editable context. If there is a conflict, follow the
  user-editable AGENTS rules.

## Authorization And Assumptions

- When I ask you a question, don't make code changes. Answer the question.
  When I want you to change/fix/implement something, I'll tell you explicitly.
- Never make code changes unless the user explicitly asks for a code change.
- Bug reports, error logs, repro steps, and “this seems broken” comments are
  not authorization to implement a fix.
- In those cases, explain the issue and propose a fix first.
- Don't make assumptions. When tasked with a change that needs
  specifications, ask instead of guessing what I want.
- If an instruction seems like it might be based on a mistake, say so
  explicitly instead of silently working around it.
- Feasibility gate: before editing code, verify that all requested constraints
  can hold simultaneously. If they cannot, do not implement a workaround,
  approximation, partial substitute, or silent relaxation. Stop and identify
  the exact conflicting constraints, explain why they conflict, and state what
  must change before implementation can proceed. Producing code that violates
  any stated constraint is a failed task, even if it compiles.
- Never infer that one instruction is “probably less important” unless I
  explicitly rank them.
- Do not add speculative future-proofing abstractions. Add indirection or
  wrapper types only when they are justified by current needs.
- Do not create duplicate data types with the same shape just to mark a
  boundary or rename a concept. Reuse the existing type unless there is a real
  representational, ownership, serialization, or invariant difference. If a
  separate type seems necessary, state the concrete reason before adding it.
- Model one source of truth. Do not duplicate facts in metadata/counters/indexes
  when an id/key/list already represents them. Ask if unsure.
- Optimize communication for correctness and shared-state alignment, not emotional cushioning.
- Be concise. Default to short, high-information responses. Do not enumerate
  bad alternatives or repeat background when one clear answer is available.
- If the user asks to discuss a design, answer only the relevant tradeoff and
  push back clearly when the user's suggestion conflicts with the current
  design or constraints.
- If the user’s objection contradicts the current plan/constraints, state that directly; do not invent agent fault.
- When I say "look at the latest screenshot" that means the latest file in `~/Pictures/Screenshots`

## General Coding Priorities

- Top priority for generating code: simple and readable.
- "Minimal patch" is not a goal. The goal is the smallest coherent local
  change.
- Be conservative globally, but locally thorough.
- It is good to keep a change scoped. It is bad to keep it so scoped that the
  touched code becomes inconsistent or visibly patchy.
- When changing a piece of code, do not stop at the narrowest possible diff if
  nearby code in the same local area is made inconsistent, noisier, or
  stylistically outdated by the change.
- Prefer finishing the local cleanup that the change obviously calls for, as
  long as it stays within the same responsibility and does not broaden scope
  much.
- If a refactor direction is already established in a file, continue it
  consistently instead of mixing old and new styles.
- When two adjacent code paths solve the same kind of problem, write them in
  the same style unless there is a clear reason not to.
- Do not leave half-converted code behind just to minimize diff size.
- Default to making the touched code look like it was written intentionally in
  one pass.
- Do not remove or rewrite user-authored comments that help orient readers in a
  file, such as sectioning/grouping comments, unless I explicitly ask for that.
- Follow the above rules through to their local conclusion. Do not leave behind
  code that is only justified by the pre-refactor structure.

## Impossible States And Fallbacks

- Do not add fallback branches for impossible or unspecified states just to keep
  execution going.
- Before writing a branch that handles an absent value, unknown enum variant,
  mismatched state, unexpected message, stale handle, invalid id, or failed
  lookup, classify it as one of:
  1. a specified normal case,
  2. a specified recoverable external/input error,
  3. a known stale/asynchronous race expected by the control flow, or
  4. an internal invariant violation.
- For cases 1-3, the code must make the reason clear from the local structure,
  naming, or a short comment.
- For case 4, fail fast at the point of detection with `assert!`, `expect`, or
  `panic!`. Do not hide it behind `None`, `false`, no-op branches, default
  values, empty collections, debug-only logs, or generic success returns.
- Assertions must only inspect state. Never mutate state inside an assertion;
  keep every state change in a separate, explicit statement.
- If the classification is not clear from the task/specification, stop and ask
  instead of choosing a fallback.
- Do not write code whose only purpose is to avoid crashing when the state is
  supposed to be impossible. In particular, avoid using these constructs as
  fallbacks unless the fallback is a specified normal/recoverable case:
  - `_ => ...`
  - `None => ...`
  - `unwrap_or...`
  - `is_some_and(...)` as a guard that silently skips work
  - `return Ok(())`
  - `return Ok(None)`
  - returning an equivalent no-op command/result
  - debug-only "ignored ..." logging
- When one of those constructs is used for newly touched fallback/no-op/default
  branches, it must be obvious why the case is legitimate. Otherwise use a
  fail-fast invariant check.
- Before finishing a change, review every newly added fallback/no-op/default
  branch. For each one, ask: "Would reaching this branch indicate a bug in our
  state model or a missing specification?" If yes, replace it with a fail-fast
  invariant check or ask for clarification.

## Control Flow And Helpers

- Prefer plain `if`-based control flow over `break`/`continue`.
- Only use `break` or `continue` when there is a strong reason and it clearly
  improves the code.
- Helper functions are acceptable if they contain at least one level of
  nesting or if they reduce code noise heavily. Do not extract trivial
  one-step helpers that do not pay for themselves.
- Do not add trivial forwarding helpers that only rename another function or
  wrap a single call.
- Prefer an I/O shell with a pure core. Do not hide filesystem or dialog I/O
  behind innocently named helper functions when the call site can make the side
  effect explicit.

## Workflow And Verification

- Before running commands, verify the correct working directory (`workdir`)
  for the target crate/tool to avoid failed first attempts in the wrong path.
- Do not start overlapping Cargo builds/checks/tests in parallel. They contend
  on the shared target/build directories and cause self-inflicted lock stalls.
- Do not use `CARGO_TARGET_DIR` as a routine workaround. It defeats cache
  reuse, increases memory usage, and makes iteration slower. Use the normal
  shared target dir by default.
- Don't do things that can hide errors or warnings.
- Warnings are never cosmetic unless I explicitly say they are.
- Do not suppress warnings with `#[allow(...)]`, Clippy allows, underscore-only
  bindings, `let _ = ...`, or similar warning-hiding changes unless I
  explicitly ask for that.
- If a warning appears in touched code, fix the underlying issue or stop and
  explain why you cannot fix it cleanly.
- Clean up temporary or tool-generated byproducts you created before finishing.
  Do not leave behind stray `wip/`, temp, backup, or similar files that are not
  intended project artifacts and could be accidentally committed.
- If a tool produces files that are meant to be checked in (for example,
  compile-fail expectation files), say that explicitly instead of treating them
  as disposable cleanup.
- Do not add low-value tests that merely mirror hard-coded data, freeze trivial
  implementation details, or create update friction without protecting behavior.
  Prefer tests that exercise meaningful logic, invariants, regressions, or
  externally observable behavior.
- I do use jj. If you interact with a repository, use jj, not git
- When I tell you to make a plan, I mean: write to plan.md at the repo root.
  This file can be overwritten if it exists
- When writing Markdown, stick to an 80 line limit where possible. This is only
  a soft requirement that can be violated with a good reason

## Rust Rules

- As an additional verification step, run `cargo clippy` when feasible, not
  just `cargo check` or tests.
- If `cargo clippy` reports straightforward warnings in touched code or nearby
  code, fix them instead of just reporting them.
- For routine verification after code changes, prefer plain `cargo check`
  without `-p` package filtering unless there is a concrete reason to narrow
  the check.
- Avoid structs with only a single field unless that field is private and the
  struct has methods that justify the wrapper. Otherwise they are usually just
  noise.
- Prefer function ordering from outer to inner (callers before callees) within
  a file when there is no stronger reason to do otherwise.
- Early returns are allowed when they reduce mental state: error propagation
  (`?`, `ensure!`, `bail!`), simple up-front guards, impossible states, or cases
  where continuing is meaningless (for example a closed channel/resource). Avoid
  guard-clause style for normal control flow, especially multiple mid-function
  exits that make the reader track which earlier paths may have returned.
- Do not use an early return to select between normal, mutually exclusive cases.
  When both branches are ordinary behavior, use one `if`/`else` or `match` that
  visibly contains both outcomes.
- When a state or shape should be impossible, fail fast with `assert!`,
  `expect`, or `panic!` at the point of the invariant check rather than hiding
  the issue behind fallback control flow.
- Prefer fail-fast style immediately: use `assert!`, `expect`, and iterator
  combinators (`map`/`filter_map`/collect patterns) instead of manual
  defensive `if`/`else` chains when enforcing invariants.
- Do not write `if matches!(...)`; use `if let` instead. `matches!()` is fine
  outside `if` conditions.
- Collapse nested `if let` conditions into a single `if let ... && let ...`
  chain when the inner branch only runs when both patterns match.
- Do not use `mod.rs` files. Always use `<module>.rs` as the module entry
  file.
- Prefer `vec![]` over `Vec::new()` for empty vector initialization.
- Do not silence unused values/arguments via `let _ = ...`. Keep unused
  warnings visible unless I explicitly ask for suppression.
- After writing code, do a quick reuse pass: if an existing helper/utility
  function already covers a new code path, use it instead of duplicating logic.
- Functions without a `self` parameter should not be member functions, unless
  they return `Self` (for example constructors). Otherwise use free functions.
- When parts of an implementation are not clearly specified by the current
  discussion, only write the code that is directly implied and use `todo!()`
  for the rest. Do not invent concrete behavior for unresolved design details.
