Agent skill

Rust Testing

by affaan-m in affaan-m/ECC

Patrones de pruebas en Rust incluyendo pruebas unitarias, de integración, async, basadas en propiedades, mocking y cobertura.

MITAuto-check passedTesting & QA

Install Rust Testing

skills CLI
$ npx skills add affaan-m/ECC --skill rust-testing -a claude-code

Project install by default; add -g for ~/.claude/skills/.

GitHub CLI
$ gh skill install affaan-m/ECC rust-testing --agent claude-code

Project scope by default; add --scope user for a personal install. Needs GitHub CLI 2.90.0 or later (public preview).

Manual copy
$ git clone --depth 1 https://github.com/affaan-m/ECC.git skills-src && mkdir -p .claude/skills && cp -r skills-src/docs/es/skills/rust-testing .claude/skills/rust-testing && rm -rf skills-src

Use ~/.claude/skills/ instead of .claude/skills for a personal install. The folder must contain SKILL.md.

Claude Code skills documentation · loads skills from .claude/skills/

Facts

Skill name
rust-testing
GitHub stars
275k
Token cost
~3.1k tokens
SKILL.md length
388 words
Files
1
Skills in repo
645
Repo updated
First seen
Licence
MIT

At a glance

Patrones de pruebas en Rust incluyendo pruebas unitarias, de integración, async, basadas en propiedades, mocking y cobertura.

  • Works in 7 steps: Identificar el código objetivo —… → Escribir una prueba — Usar #[test] en un… → Mockear dependencias — Usar mockall para… → …
  • Tasks that involve Test-driven development
  • SKILL.md covers Cuándo Usar, Cómo Funciona, Flujo de Trabajo TDD en Rust and Pruebas Unitarias, plus 9 more sections
  • Calls cargo

What it does

Rust Testing is an agent skill from affaan-m/ECC. Patrones de pruebas en Rust incluyendo pruebas unitarias, de integración, async, basadas en propiedades, mocking y cobertura. Sigue la metodología TDD.

Its SKILL.md is about 3.1k tokens, which your agent loads only when the skill is triggered. It is a single SKILL.md file with no bundled scripts.

It sits in Testing & QA, covering Test-driven development. It works with Rust. The repository describes itself as: The agent harness performance optimization system. Skills, instincts, memory, security, and research-first development for Claude Code, Codex, Opencode, Cursor and beyond. The licence is MIT.

When your agent uses it

  • Tasks that involve Test-driven development

Example prompts

  • “Use the rust-testing skill to patrone de pruebas en Rust incluyendo pruebas unitarias, de integración, async, basadas en propiedades, mocking y…”
  • “/rust-testing”

Workflow steps

7 steps, taken from the first numbered list in SKILL.md.

  1. Identificar el código objetivo — Encontrar la función, trait o módulo a probar
  2. Escribir una prueba — Usar #[test] en un módulo #[cfg(test)], rstest para pruebas parametrizadas, o proptest para pruebas basadas en…
  3. Mockear dependencias — Usar mockall para aislar la unidad bajo prueba
  4. Ejecutar pruebas (ROJO) — Verificar que la prueba falla con el error esperado
  5. Implementar (VERDE) — Escribir el código mínimo para que pase
  6. Refactorizar — Mejorar mientras se mantienen las pruebas en verde
  7. Verificar cobertura — Usar cargo-llvm-cov, objetivo 80%+

What it can do on your machine

Read from SKILL.md and the folder at commit ef648e0. It shows what the files ask for, not the result of running them.

  • Tool permissions

    Pre-approves nothing: there is no allowed-tools line, so your agent's usual permission prompts apply.

    From allowed-tools in the SKILL.md frontmatter.

  • Runs code

    Shell commands in SKILL.md call:

    • cargo

    From the folder's file list and the shell code blocks in SKILL.md.

  • Network

    No URLs in SKILL.md.

    From URLs in SKILL.md, links to its own repository left out.

  • Credentials

    Names no API keys, tokens, secrets or passwords.

    From names ending in _API_KEY, _TOKEN, _SECRET, _KEY or _PASSWORD in SKILL.md.

Context cost

Rust Testing loads about 3.1k tokens when it runs. Until then it costs about 41 tokens; SKILL.md has 388 words of instructions outside code blocks.

Always · name and description, kept in context so the agent knows when to use it
~41
When it runs · the whole SKILL.md, loaded when a task matches
~3.1k

Estimates: characters ÷ 4, the usual rule of thumb; real counts depend on the model's tokenizer. Scripts and assets cost tokens only if the agent reads them.

Safety

Auto-check passed

The automated check found no risky patterns in SKILL.md.

Automated static check — not a guarantee. Review scripts before installing. It scans the text of SKILL.md for risky patterns (piping downloads into a shell, reading credential files, hidden Unicode, destructive commands); files beside SKILL.md are not scanned.

SKILL.md

The full file from affaan-m/ECC at commit ef648e0, republished under its MIT licence (© affaan-m). 388 words, ~3,076 tokens.

Download SKILL.mdSave it as .claude/skills/rust-testing/SKILL.md (or your agent's skills folder).
name
rust-testing
description
Patrones de pruebas en Rust incluyendo pruebas unitarias, de integración, async, basadas en propiedades, mocking y cobertura. Sigue la metodología TDD.
origin
ECC

Patrones de Pruebas Rust

Patrones completos de pruebas en Rust para escribir pruebas confiables y mantenibles siguiendo la metodología TDD.

Cuándo Usar

  • Escribir nuevas funciones, métodos o traits en Rust
  • Agregar cobertura de pruebas a código existente
  • Crear benchmarks para código con requisitos de rendimiento
  • Implementar pruebas basadas en propiedades para validación de entrada
  • Seguir el flujo de trabajo TDD en proyectos Rust

Cómo Funciona

  1. Identificar el código objetivo — Encontrar la función, trait o módulo a probar
  2. Escribir una prueba — Usar #[test] en un módulo #[cfg(test)], rstest para pruebas parametrizadas, o proptest para pruebas basadas en propiedades
  3. Mockear dependencias — Usar mockall para aislar la unidad bajo prueba
  4. Ejecutar pruebas (ROJO) — Verificar que la prueba falla con el error esperado
  5. Implementar (VERDE) — Escribir el código mínimo para que pase
  6. Refactorizar — Mejorar mientras se mantienen las pruebas en verde
  7. Verificar cobertura — Usar cargo-llvm-cov, objetivo 80%+

Flujo de Trabajo TDD en Rust

El Ciclo ROJO-VERDE-REFACTORIZAR
ROJO        → Escribir primero una prueba que falle
VERDE       → Escribir el código mínimo para que pase
REFACTORIZAR → Mejorar el código manteniendo las pruebas en verde
REPETIR     → Continuar con el siguiente requisito
TDD Paso a Paso en Rust
rust
// ROJO: Escribir la prueba primero, usar todo!() como placeholder
pub fn add(a: i32, b: i32) -> i32 { todo!() }

#[cfg(test)]
mod tests {
    use super::*;
    #[test]
    fn test_add() { assert_eq!(add(2, 3), 5); }
}
// cargo test → panic en 'not yet implemented'
rust
// VERDE: Reemplazar todo!() con implementación mínima
pub fn add(a: i32, b: i32) -> i32 { a + b }
// cargo test → PASS, luego REFACTORIZAR manteniendo pruebas en verde

Pruebas Unitarias

Organización de Pruebas a Nivel de Módulo
rust
// src/user.rs
pub struct User {
    pub name: String,
    pub email: String,
}

impl User {
    pub fn new(name: impl Into<String>, email: impl Into<String>) -> Result<Self, String> {
        let email = email.into();
        if !email.contains('@') {
            return Err(format!("invalid email: {email}"));
        }
        Ok(Self { name: name.into(), email })
    }

    pub fn display_name(&self) -> &str {
        &self.name
    }
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn creates_user_with_valid_email() {
        let user = User::new("Alice", "alice@example.com").unwrap();
        assert_eq!(user.display_name(), "Alice");
        assert_eq!(user.email, "alice@example.com");
    }

    #[test]
    fn rejects_invalid_email() {
        let result = User::new("Bob", "not-an-email");
        assert!(result.is_err());
        assert!(result.unwrap_err().contains("invalid email"));
    }
}
Macros de Aserción
rust
assert_eq!(2 + 2, 4);                                    // Igualdad
assert_ne!(2 + 2, 5);                                    // Desigualdad
assert!(vec![1, 2, 3].contains(&2));                     // Booleano
assert_eq!(value, 42, "expected 42 but got {value}");    // Mensaje personalizado
assert!((0.1_f64 + 0.2 - 0.3).abs() < f64::EPSILON);   // Comparación de flotantes

Pruebas de Errores y Panics

Probar Retornos de Result
rust
#[test]
fn parse_returns_error_for_invalid_input() {
    let result = parse_config("}{invalid");
    assert!(result.is_err());

    // Verificar variante de error específica
    let err = result.unwrap_err();
    assert!(matches!(err, ConfigError::ParseError(_)));
}

#[test]
fn parse_succeeds_for_valid_input() -> Result<(), Box<dyn std::error::Error>> {
    let config = parse_config(r#"{"port": 8080}"#)?;
    assert_eq!(config.port, 8080);
    Ok(()) // La prueba falla si algún ? retorna Err
}
Probar Panics
rust
#[test]
#[should_panic]
fn panics_on_empty_input() {
    process(&[]);
}

#[test]
#[should_panic(expected = "index out of bounds")]
fn panics_with_specific_message() {
    let v: Vec<i32> = vec![];
    let _ = v[0];
}

Pruebas de Integración

Estructura de Archivos
text
my_crate/
├── src/
│   └── lib.rs
├── tests/              # Pruebas de integración
│   ├── api_test.rs     # Cada archivo es un binario de prueba separado
│   ├── db_test.rs
│   └── common/         # Utilidades de prueba compartidas
│       └── mod.rs
Escribir Pruebas de Integración
rust
// tests/api_test.rs
use my_crate::{App, Config};

#[test]
fn full_request_lifecycle() {
    let config = Config::test_default();
    let app = App::new(config);

    let response = app.handle_request("/health");
    assert_eq!(response.status, 200);
    assert_eq!(response.body, "OK");
}

Pruebas Async

Con Tokio
rust
#[tokio::test]
async fn fetches_data_successfully() {
    let client = TestClient::new().await;
    let result = client.get("/data").await;
    assert!(result.is_ok());
    assert_eq!(result.unwrap().items.len(), 3);
}

#[tokio::test]
async fn handles_timeout() {
    use std::time::Duration;
    let result = tokio::time::timeout(
        Duration::from_millis(100),
        slow_operation(),
    ).await;

    assert!(result.is_err(), "should have timed out");
}

Patrones de Organización de Pruebas

Pruebas Parametrizadas con rstest
rust
use rstest::{rstest, fixture};

#[rstest]
#[case("hello", 5)]
#[case("", 0)]
#[case("rust", 4)]
fn test_string_length(#[case] input: &str, #[case] expected: usize) {
    assert_eq!(input.len(), expected);
}

// Fixtures
#[fixture]
fn test_db() -> TestDb {
    TestDb::new_in_memory()
}

#[rstest]
fn test_insert(test_db: TestDb) {
    test_db.insert("key", "value");
    assert_eq!(test_db.get("key"), Some("value".into()));
}
Helpers de Prueba
rust
#[cfg(test)]
mod tests {
    use super::*;

    /// Crea un usuario de prueba con valores predeterminados sensatos.
    fn make_user(name: &str) -> User {
        User::new(name, &format!("{name}@test.com")).unwrap()
    }

    #[test]
    fn user_display() {
        let user = make_user("alice");
        assert_eq!(user.display_name(), "alice");
    }
}

Pruebas Basadas en Propiedades con proptest

Pruebas de Propiedades Básicas
rust
use proptest::prelude::*;

proptest! {
    #[test]
    fn encode_decode_roundtrip(input in ".*") {
        let encoded = encode(&input);
        let decoded = decode(&encoded).unwrap();
        assert_eq!(input, decoded);
    }

    #[test]
    fn sort_preserves_length(mut vec in prop::collection::vec(any::<i32>(), 0..100)) {
        let original_len = vec.len();
        vec.sort();
        assert_eq!(vec.len(), original_len);
    }

    #[test]
    fn sort_produces_ordered_output(mut vec in prop::collection::vec(any::<i32>(), 0..100)) {
        vec.sort();
        for window in vec.windows(2) {
            assert!(window[0] <= window[1]);
        }
    }
}
Estrategias Personalizadas
rust
use proptest::prelude::*;

fn valid_email() -> impl Strategy<Value = String> {
    ("[a-z]{1,10}", "[a-z]{1,5}")
        .prop_map(|(user, domain)| format!("{user}@{domain}.com"))
}

proptest! {
    #[test]
    fn accepts_valid_emails(email in valid_email()) {
        assert!(User::new("Test", &email).is_ok());
    }
}

Mocking con mockall

Mocking Basado en Traits
rust
use mockall::{automock, predicate::eq};

#[automock]
trait UserRepository {
    fn find_by_id(&self, id: u64) -> Option<User>;
    fn save(&self, user: &User) -> Result<(), StorageError>;
}

#[test]
fn service_returns_user_when_found() {
    let mut mock = MockUserRepository::new();
    mock.expect_find_by_id()
        .with(eq(42))
        .times(1)
        .returning(|_| Some(User { id: 42, name: "Alice".into() }));

    let service = UserService::new(Box::new(mock));
    let user = service.get_user(42).unwrap();
    assert_eq!(user.name, "Alice");
}

#[test]
fn service_returns_none_when_not_found() {
    let mut mock = MockUserRepository::new();
    mock.expect_find_by_id()
        .returning(|_| None);

    let service = UserService::new(Box::new(mock));
    assert!(service.get_user(99).is_none());
}
Show full SKILL.md (155 more words)Show less

Pruebas de Documentación

Documentación Ejecutable
rust
/// Suma dos números.
///
/// # Examples
///
/// ```
/// use my_crate::add;
///
/// assert_eq!(add(2, 3), 5);
/// assert_eq!(add(-1, 1), 0);
/// ```
pub fn add(a: i32, b: i32) -> i32 {
    a + b
}

/// Parsea una cadena de configuración.
///
/// # Errors
///
/// Retorna `Err` si la entrada no es TOML válido.
///
/// ```no_run
/// use my_crate::parse_config;
///
/// let config = parse_config(r#"port = 8080"#).unwrap();
/// assert_eq!(config.port, 8080);
/// ```
///
/// ```no_run
/// use my_crate::parse_config;
///
/// assert!(parse_config("}{invalid").is_err());
/// ```
pub fn parse_config(input: &str) -> Result<Config, ParseError> {
    todo!()
}

Benchmarks con Criterion

toml
# Cargo.toml
[dev-dependencies]
criterion = { version = "0.5", features = ["html_reports"] }

[[bench]]
name = "benchmark"
harness = false
rust
// benches/benchmark.rs
use criterion::{black_box, criterion_group, criterion_main, Criterion};

fn fibonacci(n: u64) -> u64 {
    match n {
        0 | 1 => n,
        _ => fibonacci(n - 1) + fibonacci(n - 2),
    }
}

fn bench_fibonacci(c: &mut Criterion) {
    c.bench_function("fib 20", |b| b.iter(|| fibonacci(black_box(20))));
}

criterion_group!(benches, bench_fibonacci);
criterion_main!(benches);

Cobertura de Pruebas

Ejecutar Cobertura
bash
# Instalar: cargo install cargo-llvm-cov (o usar taiki-e/install-action en CI)
cargo llvm-cov                    # Resumen
cargo llvm-cov --html             # Reporte HTML
cargo llvm-cov --lcov > lcov.info # Formato LCOV para CI
cargo llvm-cov --fail-under-lines 80  # Fallar si está por debajo del umbral
Objetivos de Cobertura
Tipo de CódigoObjetivo
Lógica de negocio crítica100%
API pública90%+
Código general80%+
Bindings generados / FFIExcluir

Comandos de Prueba

bash
cargo test                        # Ejecutar todas las pruebas
cargo test -- --nocapture         # Mostrar salida de println
cargo test test_name              # Ejecutar pruebas que coincidan con el patrón
cargo test --lib                  # Solo pruebas unitarias
cargo test --test api_test        # Solo pruebas de integración
cargo test --doc                  # Solo pruebas de documentación
cargo test --no-fail-fast         # No detener al primer fallo
cargo test -- --ignored           # Ejecutar pruebas ignoradas

Buenas Prácticas

HACER:

  • Escribir pruebas PRIMERO (TDD)
  • Usar módulos #[cfg(test)] para pruebas unitarias
  • Probar comportamiento, no implementación
  • Usar nombres de prueba descriptivos que expliquen el escenario
  • Preferir assert_eq! sobre assert! para mejores mensajes de error
  • Usar ? en pruebas que retornan Result para salida de errores más limpia
  • Mantener las pruebas independientes — sin estado mutable compartido

NO HACER:

  • Usar #[should_panic] cuando se puede probar Result::is_err()
  • Mockear todo — preferir pruebas de integración cuando sea factible
  • Ignorar pruebas inestables — corregirlas o ponerlas en cuarentena
  • Usar sleep() en pruebas — usar canales, barreras o tokio::time::pause()
  • Omitir las pruebas de rutas de error

Integración con CI

yaml
# GitHub Actions
test:
  runs-on: ubuntu-latest
  steps:
    - uses: actions/checkout@v4
    - uses: dtolnay/rust-toolchain@stable
      with:
        components: clippy, rustfmt

    - name: Check formatting
      run: cargo fmt --check

    - name: Clippy
      run: cargo clippy -- -D warnings

    - name: Run tests
      run: cargo test

    - uses: taiki-e/install-action@cargo-llvm-cov

    - name: Coverage
      run: cargo llvm-cov --fail-under-lines 80

Recuerda: Las pruebas son documentación. Muestran cómo debe usarse tu código. Escríbelas con claridad y mantenlas actualizadas.

© affaan-m, MIT. Rendered from Markdown: HTML in the file is shown as text, images as links, and headings moved down two levels. Raw file

Files

Just SKILL.md in docs/es/skills/rust-testing of affaan-m/ECC.

Open the folder on GitHubat commit ef648e0

Compare with similar skills

Rust Testing next to the 5 skills that share the most tags, products or categories with it. Stars are the repository's; “used in” counts other GitHub owners with a copy.

Rust Testing compared with similar skills
SkillStarsUsed inTokensAuto-checkLicenceRepo updated
Rust Testing this skillaffaan-m/ECC275k—~3.1kAutomated safety check: PassMIT
Rust TDD Workflowrtk-ai/rtk83k—~753Automated safety check: NotesApache-2.0
RTK Filter TDD in Rustrtk-ai/rtk83k—~1.9kAutomated safety check: NotesApache-2.0
TDDccusage/ccusage19k—~665Automated safety check: PassCustom licence
Implementmag123c/toktrack193—~353Automated safety check: PassMIT
Rust Testingkurealnum/dotfiles2906 repos~2.9kAutomated safety check: PassNone

Similar skills

  • Enforces red-green-refactor for Rust work, with idiomatic test patterns, a naming convention and a pre-commit gate of cargo fmt, clippy and test.

    83k GitHub stars~753 tokensUpdated today
    Testing & QAAuto-check: notes
  • Enforces red-green-refactor for new RTK output filters in Rust, using real captured fixtures, snapshot tests with insta and token-savings assertions.

    83k GitHub stars~1.9k tokensUpdated today
    Testing & QAAuto-check: notes
  • TDD

    ccusage/ccusage

    Guides t-wada Red-Green-Refactor TDD for ccusage logic changes.

    19k GitHub stars~665 tokensUpdated today
    Testing & QAAuto-check passed
  • Implement

    mag123c/toktrack

    TDD implementation (RED→GREEN→REFACTOR) → verify → review. An agent skill from mag123c/toktrack.

    193 GitHub stars~353 tokensUpdated 6 days ago
    Testing & QAAuto-check passed
  • Rust Testing

    kurealnum/dotfiles

    Rust testing patterns including unit tests, integration tests, async testing, property-based testing, mocking, and coverage.

    290 GitHub starsUsed in 6 repos~2.9k tokens
    Testing & QAAuto-check passed
  • Growing Outside In Systems

    lexler/skill-factory

    Drive feature development using Outside-In TDD with Hexagonal Architecture.

    239 GitHub starsUsed in 1 repo~1.9k tokens
    Testing & QAAuto-check passed

More from affaan-m/ECC

All 645 skills in this repo
  • Videodb

    affaan-m/ECC

    Ingest, index, search, edit, and monitor video and audio with the VideoDB Python SDK — upload from files, URLs, or RTSP feeds, build spoken and scene indexes with timestamped search and playable…

    275k GitHub starsUsed in 3 repos~3.5k tokens
    Auto-check: notes
  • Rules Distillation

    affaan-m/ECC

    Scans installed skills for principles that recur across them and proposes rule-file changes: append, revise, add a section, create a file or leave as covered.

    275k GitHub starsUsed in 2 repos~2.3k tokens
    Auto-check passed
  • Builds DRAFT counterparty agreements from one markdown template and a small JSON spec per party, with clauses picked by the party's role.

    275k GitHub stars~2.9k tokensUpdated 3 days ago
    Auto-check passed
  • Measures whether agents actually follow a skill, rule or agent definition by generating scenarios at three strictness levels and scoring tool-call traces.

    275k GitHub starsUsed in 1 repo~623 tokens
    Auto-check passed
  • Instinct-based learning system that observes sessions via hooks, creates atomic instincts with confidence scoring, and evolves them into skills/commands/agents.

    275k GitHub stars~3.5k tokensUpdated 3 days ago
    Auto-check passed
  • Adds one optional external Codex critique that tries to break a council's decision draft, sent to OpenAI only after you consent.

    275k GitHub stars~1.5k tokensUpdated 3 days ago
    Auto-check passed

Works with

Categories

Questions about Rust Testing

What does Rust Testing do?

Patrones de pruebas en Rust incluyendo pruebas unitarias, de integración, async, basadas en propiedades, mocking y cobertura. Rust Testing is an agent skill from affaan-m/ECC. Patrones de pruebas en Rust incluyendo pruebas unitarias, de integración, async, basadas en propiedades, mocking y cobertura.

When should I use Rust Testing?

Rust Testing fits situations like: tasks that involve Test-driven development.

How do I install Rust Testing in Claude Code?

Run `npx skills add affaan-m/ECC --skill rust-testing -a claude-code`. Or copy the skill folder (docs/es/skills/rust-testing in affaan-m/ECC) into .claude/skills/rust-testing in your project. Claude Code loads it when a task matches its description.

How do I install Rust Testing in Codex?

Run `npx skills add affaan-m/ECC --skill rust-testing -a codex`. Or copy the skill folder (docs/es/skills/rust-testing in affaan-m/ECC) into .agents/skills/rust-testing in your project. Codex loads it when a task matches its description.

Can I use Rust Testing in Cursor, Gemini CLI or GitHub Copilot?

Cursor, Gemini CLI, GitHub Copilot and OpenCode also load SKILL.md folders. With the skills CLI, run `npx skills add affaan-m/ECC --skill rust-testing -a cursor` (or -a gemini-cli, github-copilot or opencode for the others). To copy it by hand, put the folder in .cursor/skills/rust-testing, .gemini/skills/rust-testing, .github/skills/rust-testing and .opencode/skills/rust-testing in your project.

What does Rust Testing need to run?

Going by SKILL.md and its folder, Rust Testing needs the command-line tools its instructions call (cargo).

Does Rust Testing access the network?

SKILL.md contains no URLs. Any network use would come from the scripts or tools the agent runs. This is read from the text; nothing was executed.

Is Rust Testing safe to install?

Our automated static check of SKILL.md found no risky patterns, such as piping downloads into a shell, reading credential files or hidden Unicode. It is not a guarantee. Review the folder before installing.

What licence does Rust Testing use?

Rust Testing is published under the MIT licence (the repository's licence). It allows redistribution, so the full SKILL.md is shown on this page.

How many tokens does Rust Testing use?

About 3.1k tokens (SKILL.md is roughly 12k characters). Agents keep only the skill's name and description in context until a task matches; then they load SKILL.md in full.

What are the alternatives to Rust Testing?

Skills that share tags, products or a category with Rust Testing: Rust TDD Workflow (rtk-ai/rtk, 83k stars), RTK Filter TDD in Rust (rtk-ai/rtk, 83k stars), TDD (ccusage/ccusage, 19k stars) and Implement (mag123c/toktrack, 193 stars). The comparison table on this page puts their stars, adoption, token cost, safety result and licence side by side.

Who maintains Rust Testing?

affaan-m (a GitHub user) maintains it in affaan-m/ECC, which has 275,023 GitHub stars. The repository holds 645 skills in this directory. The repository was last updated on October 5, 2026.

Source: affaan-m/ECC on GitHub. Facts on this page come from the repository at the commit we read; the author's words are quoted as theirs.