Skip to content

docs: writing style, sentence structure, punctuation #394

@KSXGitHub

Description

@KSXGitHub

This is from a PR on an unrelated codebase:

Diff
diff --git a/.github/copilot-instructions.md b/.github/copilot-instructions.md
index f04b72b..c514dc4 100644
--- a/.github/copilot-instructions.md
+++ b/.github/copilot-instructions.md
@@ -4,17 +4,18 @@ Read and follow the CONTRIBUTING.md file in this repository for all code style c
 
 ## Quick Reference
 
-- Commit format: Conventional Commits — `type(scope): lowercase description`
-- Use descriptive variable and closure parameter names by default — single letters are only allowed in: conventional names (`n` for count, `f` for formatter), comparison closures (`|a, b|`), trivial single-expression closures, fold accumulators, index variables (`i`/`j`/`k` in short closures or index-based loops only), and test fixtures (identical roles only). Never use single letters in multi-line functions or closures
-- Use `pipe-trait` for chaining through unary functions (constructors, `Some`, `Ok`, free functions, etc.), avoiding nested calls, and continuing method chains — but not for simple standalone calls (prefer `foo(value)` over `value.pipe(foo)`)
-- Use `command-extra` (`CommandExtra` trait) when building `std::process::Command` — use `.with_arg(...)`, `.with_env(...)`, etc. instead of `.arg(...)`, `.env(...)` to keep construction as a single owned expression chain
-- Prefer `where` clauses for multiple trait bounds
-- Minimize `unwrap()` in non-test code — use proper error handling
-- Prefer `#[cfg_attr(..., ignore = "reason")]` over `#[cfg(...)]` to skip tests — use `#[cfg]` on tests only when the code cannot compile under the condition (e.g., references types/functions that don't exist on other platforms)
-- Install toolchain before running tests: `rustup toolchain install "$(< rust-toolchain)" && rustup component add --toolchain "$(< rust-toolchain)" rustfmt clippy`
-- Run `cargo fmt -- --check && cargo clippy --all-targets && cargo test` to validate changes
-- **ALWAYS run the full Rust test suite** (`cargo fmt -- --check && cargo clippy --all-targets && cargo test`) before committing, regardless of how trivial the change seems — this includes documentation-only changes, comment edits, and config changes
-- If a sync test fails, read its error message carefully and run the exact command it tells you to run
-- Run CSpell check if necessary (with `pnpm install --frozen-lockfile && pnpm exec cspell lint --gitignore '**'`).
-- When the user provides a diff and you need to update the files, don't manually interpret each hunk (that'd be slow); apply it with `git apply` instead. If the user provides a diff for context or discussion rather than as a change to apply, respond accordingly instead.
-- `gh` (GitHub CLI) is not installed — do not attempt to use it
+- Commit format: Conventional Commits. Pattern: `type(scope): lowercase description`. The scope is optional.
+- Write documentation, comments, and other prose for ease of understanding first. Prefer a formal tone when it does not hurt clarity, and use complete sentences. Avoid mid-sentence breaks introduced by em dashes or long parenthetical clauses. Em dashes are a reliable symptom of loose phrasing; when one appears, restructure the surrounding sentence so each clause stands on its own rather than swapping the em dash for another punctuation mark.
+- Use descriptive names for variables and closure parameters. Single letters are permitted only in these cases: (1) conventional names like `n` for count or `f` for formatter; (2) comparison closures like `|a, b|`; (3) trivial single-expression closures; (4) fold accumulators; (5) index variables `i`/`j`/`k` in short closures or index-based loops; and (6) test fixtures with identical roles. Single letters are never permitted in multi-line functions or closures.
+- Use `pipe-trait` to chain through unary functions such as constructors, `Some`, `Ok`, and free functions. Use it to flatten nested calls and to continue method chains. Do not use it for simple standalone calls; prefer `foo(value)` over `value.pipe(foo)`.
+- Use the `command-extra` crate (the `CommandExtra` trait) when building `std::process::Command`. Call `.with_arg(...)`, `.with_env(...)`, and similar methods rather than `.arg(...)` or `.env(...)`, so construction remains a single owned expression chain.
+- Prefer `where` clauses when a type has multiple trait bounds.
+- Minimize `unwrap()` in non-test code. Use proper error handling instead.
+- Prefer `#[cfg_attr(..., ignore = "reason")]` over `#[cfg(...)]` when skipping tests. Use `#[cfg]` on tests only when the code cannot compile under the condition, such as when it references types or functions that do not exist on other platforms.
+- Install the toolchain before running tests: `rustup toolchain install "$(< rust-toolchain)" && rustup component add --toolchain "$(< rust-toolchain)" rustfmt clippy`.
+- Validate changes with `cargo fmt -- --check && cargo clippy --all-targets && cargo test`.
+- **Always run the full Rust test suite** (`cargo fmt -- --check && cargo clippy --all-targets && cargo test`) before every commit. This rule applies to all changes, including documentation changes, comment edits, and config updates.
+- When a sync test fails, read its error message and run the exact command it reports.
+- Run the CSpell spell check when a change may introduce new words: `pnpm install --frozen-lockfile && pnpm exec cspell lint --gitignore '**'`.
+- When the user provides a diff to apply, run `git apply` rather than interpreting each hunk manually. When a diff is provided for context or discussion, respond accordingly.
+- The `gh` (GitHub CLI) is not installed. Do not attempt to use it.
diff --git a/AGENTS.md b/AGENTS.md
index bba0b1e..c7aaf3c 100644
--- a/AGENTS.md
+++ b/AGENTS.md
@@ -4,16 +4,17 @@ Read and follow the CONTRIBUTING.md file in this repository for all code style c
 
 ## Quick Reference
 
-- Commit format: Conventional Commits — `type(scope): lowercase description`
-- Use descriptive variable and closure parameter names by default — single letters are only allowed in: conventional names (`n` for count, `f` for formatter), comparison closures (`|a, b|`), trivial single-expression closures, fold accumulators, index variables (`i`/`j`/`k` in short closures or index-based loops only), and test fixtures (identical roles only). Never use single letters in multi-line functions or closures
-- Use `pipe-trait` for chaining through unary functions (constructors, `Some`, `Ok`, free functions, etc.), avoiding nested calls, and continuing method chains — but not for simple standalone calls (prefer `foo(value)` over `value.pipe(foo)`)
-- Use `command-extra` (`CommandExtra` trait) when building `std::process::Command` — use `.with_arg(...)`, `.with_env(...)`, etc. instead of `.arg(...)`, `.env(...)` to keep construction as a single owned expression chain
-- Prefer `where` clauses for multiple trait bounds
-- Minimize `unwrap()` in non-test code — use proper error handling
-- Prefer `#[cfg_attr(..., ignore = "reason")]` over `#[cfg(...)]` to skip tests — use `#[cfg]` on tests only when the code cannot compile under the condition (e.g., references types/functions that don't exist on other platforms)
-- Install toolchain before running tests: `rustup toolchain install "$(< rust-toolchain)" && rustup component add --toolchain "$(< rust-toolchain)" rustfmt clippy`
-- Run `cargo fmt -- --check && cargo clippy --all-targets && cargo test` to validate changes
-- **ALWAYS run the full Rust test suite** (`cargo fmt -- --check && cargo clippy --all-targets && cargo test`) before committing, regardless of how trivial the change seems — this includes documentation-only changes, comment edits, and config changes
-- If a sync test fails, read its error message carefully and run the exact command it tells you to run
-- Run CSpell check if necessary (with `pnpm install --frozen-lockfile && pnpm exec cspell lint --gitignore '**'`).
-- When the user provides a diff and you need to update the files, don't manually interpret each hunk (that'd be slow); apply it with `git apply` instead. If the user provides a diff for context or discussion rather than as a change to apply, respond accordingly instead.
+- Commit format: Conventional Commits. Pattern: `type(scope): lowercase description`. The scope is optional.
+- Write documentation, comments, and other prose for ease of understanding first. Prefer a formal tone when it does not hurt clarity, and use complete sentences. Avoid mid-sentence breaks introduced by em dashes or long parenthetical clauses. Em dashes are a reliable symptom of loose phrasing; when one appears, restructure the surrounding sentence so each clause stands on its own rather than swapping the em dash for another punctuation mark.
+- Use descriptive names for variables and closure parameters. Single letters are permitted only in these cases: (1) conventional names like `n` for count or `f` for formatter; (2) comparison closures like `|a, b|`; (3) trivial single-expression closures; (4) fold accumulators; (5) index variables `i`/`j`/`k` in short closures or index-based loops; and (6) test fixtures with identical roles. Single letters are never permitted in multi-line functions or closures.
+- Use `pipe-trait` to chain through unary functions such as constructors, `Some`, `Ok`, and free functions. Use it to flatten nested calls and to continue method chains. Do not use it for simple standalone calls; prefer `foo(value)` over `value.pipe(foo)`.
+- Use the `command-extra` crate (the `CommandExtra` trait) when building `std::process::Command`. Call `.with_arg(...)`, `.with_env(...)`, and similar methods rather than `.arg(...)` or `.env(...)`, so construction remains a single owned expression chain.
+- Prefer `where` clauses when a type has multiple trait bounds.
+- Minimize `unwrap()` in non-test code. Use proper error handling instead.
+- Prefer `#[cfg_attr(..., ignore = "reason")]` over `#[cfg(...)]` when skipping tests. Use `#[cfg]` on tests only when the code cannot compile under the condition, such as when it references types or functions that do not exist on other platforms.
+- Install the toolchain before running tests: `rustup toolchain install "$(< rust-toolchain)" && rustup component add --toolchain "$(< rust-toolchain)" rustfmt clippy`.
+- Validate changes with `cargo fmt -- --check && cargo clippy --all-targets && cargo test`.
+- **Always run the full Rust test suite** (`cargo fmt -- --check && cargo clippy --all-targets && cargo test`) before every commit. This rule applies to all changes, including documentation changes, comment edits, and config updates.
+- When a sync test fails, read its error message and run the exact command it reports.
+- Run the CSpell spell check when a change may introduce new words: `pnpm install --frozen-lockfile && pnpm exec cspell lint --gitignore '**'`.
+- When the user provides a diff to apply, run `git apply` rather than interpreting each hunk manually. When a diff is provided for context or discussion, respond accordingly.
diff --git a/CLAUDE.md b/CLAUDE.md
index bba0b1e..c7aaf3c 100644
--- a/CLAUDE.md
+++ b/CLAUDE.md
@@ -4,16 +4,17 @@ Read and follow the CONTRIBUTING.md file in this repository for all code style c
 
 ## Quick Reference
 
-- Commit format: Conventional Commits — `type(scope): lowercase description`
-- Use descriptive variable and closure parameter names by default — single letters are only allowed in: conventional names (`n` for count, `f` for formatter), comparison closures (`|a, b|`), trivial single-expression closures, fold accumulators, index variables (`i`/`j`/`k` in short closures or index-based loops only), and test fixtures (identical roles only). Never use single letters in multi-line functions or closures
-- Use `pipe-trait` for chaining through unary functions (constructors, `Some`, `Ok`, free functions, etc.), avoiding nested calls, and continuing method chains — but not for simple standalone calls (prefer `foo(value)` over `value.pipe(foo)`)
-- Use `command-extra` (`CommandExtra` trait) when building `std::process::Command` — use `.with_arg(...)`, `.with_env(...)`, etc. instead of `.arg(...)`, `.env(...)` to keep construction as a single owned expression chain
-- Prefer `where` clauses for multiple trait bounds
-- Minimize `unwrap()` in non-test code — use proper error handling
-- Prefer `#[cfg_attr(..., ignore = "reason")]` over `#[cfg(...)]` to skip tests — use `#[cfg]` on tests only when the code cannot compile under the condition (e.g., references types/functions that don't exist on other platforms)
-- Install toolchain before running tests: `rustup toolchain install "$(< rust-toolchain)" && rustup component add --toolchain "$(< rust-toolchain)" rustfmt clippy`
-- Run `cargo fmt -- --check && cargo clippy --all-targets && cargo test` to validate changes
-- **ALWAYS run the full Rust test suite** (`cargo fmt -- --check && cargo clippy --all-targets && cargo test`) before committing, regardless of how trivial the change seems — this includes documentation-only changes, comment edits, and config changes
-- If a sync test fails, read its error message carefully and run the exact command it tells you to run
-- Run CSpell check if necessary (with `pnpm install --frozen-lockfile && pnpm exec cspell lint --gitignore '**'`).
-- When the user provides a diff and you need to update the files, don't manually interpret each hunk (that'd be slow); apply it with `git apply` instead. If the user provides a diff for context or discussion rather than as a change to apply, respond accordingly instead.
+- Commit format: Conventional Commits. Pattern: `type(scope): lowercase description`. The scope is optional.
+- Write documentation, comments, and other prose for ease of understanding first. Prefer a formal tone when it does not hurt clarity, and use complete sentences. Avoid mid-sentence breaks introduced by em dashes or long parenthetical clauses. Em dashes are a reliable symptom of loose phrasing; when one appears, restructure the surrounding sentence so each clause stands on its own rather than swapping the em dash for another punctuation mark.
+- Use descriptive names for variables and closure parameters. Single letters are permitted only in these cases: (1) conventional names like `n` for count or `f` for formatter; (2) comparison closures like `|a, b|`; (3) trivial single-expression closures; (4) fold accumulators; (5) index variables `i`/`j`/`k` in short closures or index-based loops; and (6) test fixtures with identical roles. Single letters are never permitted in multi-line functions or closures.
+- Use `pipe-trait` to chain through unary functions such as constructors, `Some`, `Ok`, and free functions. Use it to flatten nested calls and to continue method chains. Do not use it for simple standalone calls; prefer `foo(value)` over `value.pipe(foo)`.
+- Use the `command-extra` crate (the `CommandExtra` trait) when building `std::process::Command`. Call `.with_arg(...)`, `.with_env(...)`, and similar methods rather than `.arg(...)` or `.env(...)`, so construction remains a single owned expression chain.
+- Prefer `where` clauses when a type has multiple trait bounds.
+- Minimize `unwrap()` in non-test code. Use proper error handling instead.
+- Prefer `#[cfg_attr(..., ignore = "reason")]` over `#[cfg(...)]` when skipping tests. Use `#[cfg]` on tests only when the code cannot compile under the condition, such as when it references types or functions that do not exist on other platforms.
+- Install the toolchain before running tests: `rustup toolchain install "$(< rust-toolchain)" && rustup component add --toolchain "$(< rust-toolchain)" rustfmt clippy`.
+- Validate changes with `cargo fmt -- --check && cargo clippy --all-targets && cargo test`.
+- **Always run the full Rust test suite** (`cargo fmt -- --check && cargo clippy --all-targets && cargo test`) before every commit. This rule applies to all changes, including documentation changes, comment edits, and config updates.
+- When a sync test fails, read its error message and run the exact command it reports.
+- Run the CSpell spell check when a change may introduce new words: `pnpm install --frozen-lockfile && pnpm exec cspell lint --gitignore '**'`.
+- When the user provides a diff to apply, run `git apply` rather than interpreting each hunk manually. When a diff is provided for context or discussion, respond accordingly.
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index f9f9218..848e274 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -28,20 +28,20 @@ Use **descriptive names** for variables and closure parameters by default. Singl
 
 #### When single-letter names are allowed
 
-- **Comparison closures:** `|a, b|` in `sort_by`, `cmp`, or similar two-argument comparison callbacks — this is idiomatic Rust.
+- **Comparison closures:** `|a, b|` in `sort_by`, `cmp`, or similar two-argument comparison callbacks. This is idiomatic Rust.
 
   ```rust
   items.sort_by(|a, b| a.name.cmp(&b.name));

-- Conventional single-letter names: n for a natural number (unsigned integer / count), f for a fmt::Formatter, and similar well-established conventions from math or the Rust standard library. Note: for indices, use index, idx, or *_index — not n. (For i/j/k, see the dedicated rule below.)
+- Conventional single-letter names: n for a natural number (unsigned integer / count); f for a fmt::Formatter; and similar well-established conventions from math or the Rust standard library. Note: for indices, use index, idx, or *_index, not n. (For i/j/k, see the dedicated rule below.)

fn with_capacity(n: usize) -> Self { todo!() }
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { todo!() }

-- Index variables (i, j, k): These may only be used in two contexts: (1) short closures, and (2) index-based loops/iterations (rare in Rust). In all other cases, use index, idx, or *_index.
+- Index variables (i, j, k): These may only be used in two contexts: short closures and index-based loops. In all other cases, use index, idx, or *_index.

  • Trivial single-expression closures: A closure whose body is a single field access, method call, or wrapper may use a single letter when the type and purpose are obvious from context.

@@ -55,7 +55,7 @@ Use descriptive names for variables and closure parameters by default. Singl
.fold(PathBuf::new(), |acc, x| acc.join(x))


-- **Test fixtures:** `let a`, `let b`, `let c` for interchangeable specimens with identical roles in equality or comparison tests. Do not use single letters when the variables have distinct roles — use `actual`/`expected` or similar descriptive names instead.
+- **Test fixtures:** `let a`, `let b`, `let c` for interchangeable specimens with identical roles in equality or comparison tests. Do not use single letters when the variables have distinct roles; use `actual`/`expected` or similar descriptive names instead.

#### When single-letter names are NOT allowed

@@ -99,23 +99,23 @@ where

### Error Handling

-- Minimize `unwrap()` in non-test code — use proper error propagation. `unwrap()` is acceptable in tests and for provably infallible operations (with a comment explaining why). When deliberately ignoring an error, use `.ok()` with a comment explaining why.
+- Minimize `unwrap()` in non-test code; use proper error propagation. `unwrap()` is acceptable in tests and for provably infallible operations (with a comment explaining why). When deliberately ignoring an error, use `.ok()` with a comment explaining why.

### Conditional Test Skipping: `#[cfg]` vs `#[cfg_attr(..., ignore)]`

-When a test cannot run under certain conditions (e.g., wrong platform), prefer `#[cfg_attr(..., ignore)]` over `#[cfg(...)]` to skip it. This way the test is still compiled on all configurations — catching type errors and regressions early — but simply skipped at runtime.
+When a test cannot run under certain conditions, such as on the wrong platform, prefer `#[cfg_attr(..., ignore)]` over `#[cfg(...)]` to skip it. The test still compiles on every configuration and is only skipped at runtime. This approach catches type errors and regressions that a `#[cfg]` skip would hide.

-Use `#[cfg]` on tests **only** when the code cannot compile under the condition — for example, when the test references types, functions, or trait methods that are gated behind `#[cfg]` and do not exist on other platforms.
+Use `#[cfg]` on tests **only** when the code cannot compile under the condition. An example is a test that uses platform-specific types or functions gated behind `#[cfg]`.

Prefer including a reason string in the `ignore` attribute to explain why the test is skipped.

```rust
-// Good — test compiles everywhere, skipped at runtime on non-unix
+// Good: test compiles everywhere, skipped at runtime on non-unix
#[test]
#[cfg_attr(not(unix), ignore = "only unix path separators are tested")]
fn unix_path_logic() { /* uses hardcoded unix paths but no unix-only types */ }

-// Good — test CANNOT compile on non-unix (uses unix-only types)
+// Good: test CANNOT compile on non-unix (uses unix-only types)
#[cfg(unix)]
#[test]
fn unix_only_types() { /* uses OsStrExt which only exists on unix */ }
@@ -125,14 +125,14 @@ fn unix_only_types() { /* uses OsStrExt which only exists on unix */ }

This codebase uses the [`pipe-trait`](https://docs.rs/pipe-trait) crate for method-chaining through unary functions, keeping code in a natural left-to-right reading order. Import it as `use pipe_trait::Pipe;`.

-Any callable that takes a single argument works with `.pipe()` — free functions, closures, newtype constructors, enum variant constructors, `Some`, `Ok`, `Err`, trait methods like `From::from`, etc.
+Any callable that takes a single argument works with `.pipe()`. This includes free functions, closures, newtype constructors, enum variant constructors, `Some`, `Ok`, `Err`, and trait methods such as `From::from`.

#### When to use pipe

**Chaining through a unary function at the end of an expression chain:**

```rust
-// Good — pipe keeps the chain flowing left-to-right
+// Good: pipe keeps the chain flowing left-to-right
entry.file_name().pipe(OsStringDisplay::from).pipe(Some)

@@ -149,7 +149,7 @@ let data = stdin().pipe(serde_json::from_reader::<_, JsonData>);
Continuing a method chain through a free function and back to methods:

-// Good — pipe bridges from methods to a free function and back
+// Good: pipe bridges from methods to a free function and back
path_buf
    .pipe_as_ref(fs::read_to_string)
    .map(|content| content.trim().to_owned())
@@ -157,13 +157,13 @@ path_buf

#### When NOT to use pipe

-**Simple standalone function calls** — pipe adds noise with no readability benefit:
+**Simple standalone function calls.** Pipe adds noise with no readability benefit:

```rust
-// Bad — unnecessary pipe
+// Bad: unnecessary pipe
let result = value.pipe(foo);

-// Good — just call the function directly
+// Good: just call the function directly
let result = foo(value);

@@ -171,17 +171,17 @@ let result = foo(value);

This codebase uses the command-extra crate to build std::process::Command values in a chainable, owned style. Import it as use command_extra::CommandExtra;.

-The standard Command builder methods (arg, env, current_dir, etc.) take &mut self and return &mut Command, making them unsuitable for method chains that end in an owned value. The CommandExtra extension trait provides .with_* counterparts that take ownership and return an owned Command, enabling fluent one-expression construction:
+The standard Command builder methods, such as arg, env, and current_dir, take &mut self and return &mut Command. This makes them unsuitable for method chains that end in an owned value. The CommandExtra extension trait provides .with_* counterparts that take ownership and return an owned Command, enabling fluent one-expression construction:

-// Good — fully chainable, owned style
+// Good: fully chainable, owned style
let output = Command::new("my-tool")
    .with_arg("--flag")
    .with_arg(value)
    .output()
    .expect("spawn my-tool");

-// Avoid — mutable-reference style, cannot chain with owned methods
+// Avoid: mutable-reference style, cannot chain with owned methods
let mut cmd = Command::new("my-tool");
cmd.arg("--flag");
cmd.arg(value);
@@ -199,7 +199,7 @@ rustup toolchain install "$(< rust-toolchain)"
rustup component add --toolchain "$(< rust-toolchain)" rustfmt clippy

-If you need to run the spell check locally, install the Node.js dependencies via pnpm:
+To run the spell check locally, install the Node.js dependencies with pnpm:

pnpm install --frozen-lockfile
@@ -227,7 +227,7 @@ cargo fmt -- --check && cargo clippy --all-targets && cargo test

### Spell Check

-Run the [CSpell](https://cspell.org) spell check if necessary:
+Run the [CSpell](https://cspell.org) spell check when a change may introduce new words:

```sh
pnpm exec cspell lint --no-progress --gitignore '**'
diff --git a/template/ai-instructions/copilot.md b/template/ai-instructions/copilot.md
index b458326..a887ba3 100644
--- a/template/ai-instructions/copilot.md
+++ b/template/ai-instructions/copilot.md
@@ -1 +1 @@
-- `gh` (GitHub CLI) is not installed — do not attempt to use it
+- The `gh` (GitHub CLI) is not installed. Do not attempt to use it.
diff --git a/template/ai-instructions/shared.md b/template/ai-instructions/shared.md
index bba0b1e..c7aaf3c 100644
--- a/template/ai-instructions/shared.md
+++ b/template/ai-instructions/shared.md
@@ -4,16 +4,17 @@ Read and follow the CONTRIBUTING.md file in this repository for all code style c

## Quick Reference

-- Commit format: Conventional Commits — `type(scope): lowercase description`
-- Use descriptive variable and closure parameter names by default — single letters are only allowed in: conventional names (`n` for count, `f` for formatter), comparison closures (`|a, b|`), trivial single-expression closures, fold accumulators, index variables (`i`/`j`/`k` in short closures or index-based loops only), and test fixtures (identical roles only). Never use single letters in multi-line functions or closures
-- Use `pipe-trait` for chaining through unary functions (constructors, `Some`, `Ok`, free functions, etc.), avoiding nested calls, and continuing method chains — but not for simple standalone calls (prefer `foo(value)` over `value.pipe(foo)`)
-- Use `command-extra` (`CommandExtra` trait) when building `std::process::Command` — use `.with_arg(...)`, `.with_env(...)`, etc. instead of `.arg(...)`, `.env(...)` to keep construction as a single owned expression chain
-- Prefer `where` clauses for multiple trait bounds
-- Minimize `unwrap()` in non-test code — use proper error handling
-- Prefer `#[cfg_attr(..., ignore = "reason")]` over `#[cfg(...)]` to skip tests — use `#[cfg]` on tests only when the code cannot compile under the condition (e.g., references types/functions that don't exist on other platforms)
-- Install toolchain before running tests: `rustup toolchain install "$(< rust-toolchain)" && rustup component add --toolchain "$(< rust-toolchain)" rustfmt clippy`
-- Run `cargo fmt -- --check && cargo clippy --all-targets && cargo test` to validate changes
-- **ALWAYS run the full Rust test suite** (`cargo fmt -- --check && cargo clippy --all-targets && cargo test`) before committing, regardless of how trivial the change seems — this includes documentation-only changes, comment edits, and config changes
-- If a sync test fails, read its error message carefully and run the exact command it tells you to run
-- Run CSpell check if necessary (with `pnpm install --frozen-lockfile && pnpm exec cspell lint --gitignore '**'`).
-- When the user provides a diff and you need to update the files, don't manually interpret each hunk (that'd be slow); apply it with `git apply` instead. If the user provides a diff for context or discussion rather than as a change to apply, respond accordingly instead.
+- Commit format: Conventional Commits. Pattern: `type(scope): lowercase description`. The scope is optional.
+- Write documentation, comments, and other prose for ease of understanding first. Prefer a formal tone when it does not hurt clarity, and use complete sentences. Avoid mid-sentence breaks introduced by em dashes or long parenthetical clauses. Em dashes are a reliable symptom of loose phrasing; when one appears, restructure the surrounding sentence so each clause stands on its own rather than swapping the em dash for another punctuation mark.
+- Use descriptive names for variables and closure parameters. Single letters are permitted only in these cases: (1) conventional names like `n` for count or `f` for formatter; (2) comparison closures like `|a, b|`; (3) trivial single-expression closures; (4) fold accumulators; (5) index variables `i`/`j`/`k` in short closures or index-based loops; and (6) test fixtures with identical roles. Single letters are never permitted in multi-line functions or closures.
+- Use `pipe-trait` to chain through unary functions such as constructors, `Some`, `Ok`, and free functions. Use it to flatten nested calls and to continue method chains. Do not use it for simple standalone calls; prefer `foo(value)` over `value.pipe(foo)`.
+- Use the `command-extra` crate (the `CommandExtra` trait) when building `std::process::Command`. Call `.with_arg(...)`, `.with_env(...)`, and similar methods rather than `.arg(...)` or `.env(...)`, so construction remains a single owned expression chain.
+- Prefer `where` clauses when a type has multiple trait bounds.
+- Minimize `unwrap()` in non-test code. Use proper error handling instead.
+- Prefer `#[cfg_attr(..., ignore = "reason")]` over `#[cfg(...)]` when skipping tests. Use `#[cfg]` on tests only when the code cannot compile under the condition, such as when it references types or functions that do not exist on other platforms.
+- Install the toolchain before running tests: `rustup toolchain install "$(< rust-toolchain)" && rustup component add --toolchain "$(< rust-toolchain)" rustfmt clippy`.
+- Validate changes with `cargo fmt -- --check && cargo clippy --all-targets && cargo test`.
+- **Always run the full Rust test suite** (`cargo fmt -- --check && cargo clippy --all-targets && cargo test`) before every commit. This rule applies to all changes, including documentation changes, comment edits, and config updates.
+- When a sync test fails, read its error message and run the exact command it reports.
+- Run the CSpell spell check when a change may introduce new words: `pnpm install --frozen-lockfile && pnpm exec cspell lint --gitignore '**'`.
+- When the user provides a diff to apply, run `git apply` rather than interpreting each hunk manually. When a diff is provided for context or discussion, respond accordingly.

TASKS:

  1. Analyze the diff.

  2. Adapt whatever is applicable to this codebase.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions