CommunityProgramación y desarrollogithub.com

rust-qc

Usa esta habilidad siempre que tu respuesta contenga código Rust o configuraciones de Cargo/clippy/rustfmt, o un veredicto sobre código Rust existente. Incluso tareas simples de Rust la necesitan: contiene las convenciones requeridas y una verificación fmt/clippy/doc/test que todo cambio en Rust debe pasar. Esto incluye escribir cualquier Rust nuevo (una función cuenta), corregir un error del compilador o del borrow-checker, agregar comentarios rustdoc y ejemplos, rediseñar tipos de error, refactorizar, revisar o auditar un archivo .rs o crate, y ordenar un workspace de Cargo (lints compartidos, ediciones, versiones de dependencias). Cuando el lenguaje sea Rust, usa esta habilidad primero y no permitas que una habilidad general de depuración, documentación, refactorización o revisión de código la reemplace. Saltéala solo cuando no se escriba ni juzgue código Rust: explicar conceptos, comparar lenguajes, resumir ediciones, o trabajar en otro lenguaje incluso dentro de un repositorio que también tenga Rust.

¿Qué es rust-qc?

Rust QC es una habilidad de agente de IA especializada en garantizar la calidad del código Rust. Establece un estándar único para el código Rust, basado en guías de estilo reconocidas (Rust Style Guide, Rust API Guidelines, guías de Microsoft y Google) y las prácticas observadas en crates populares como ripgrep, fd y jiff. La habilidad opera en tres modos principales: Crear (para nuevas funciones, tipos y crates), Modificar (cambios en código existente) y Auditar (revisión y evaluación del código). Cada modo tiene pasos detallados y reglas obligatorias que incluyen el formateo con rustfmt, la solidez del código unsafe, el manejo adecuado de errores y la documentación completa de elementos públicos. La habilidad se aplica en plataformas como Claude Code, Cursor y Codex, y está diseñada para trabajar antes que habilidades generales de depuración o revisión cuando se trata de Rust. Utiliza scripts de verificación (`scripts/check.sh`) y análisis avanzados con audit_scan.py para detectar problemas que clippy no puede ver. Las reglas no negociables cubren desde el formateo y la solidez hasta la estructura del código y la gestión de dependencias, asegurando que el código Rust producido sea limpio, eficiente y siga las mejores prácticas de la comunidad.

Compatible con✓Claude Code~Codex CLI~Cursor
npx skills add https://github.com/coryj627/rust-qc/tree/main/.agents/skills/rust-qc

Installed? Explore more Programación y desarrollo skills: steipete/bluebubbles, steipete/eightctl, steipete/blucli · View all 6 →

Preguntar en tu IA favorita

Abre un nuevo chat con esta habilidad de agente ya precargada.

Documentación

Rust QC

Esta habilidad establece un estándar para el código Rust y lo aplica en tres modos. Las reglas provienen de la Rust Style Guide, las Rust API Guidelines, las Microsoft Pragmatic Rust Guidelines (2026.6), la Google Rust Style Guide, y las prácticas visibles en memchr, jiff, ripgrep, fd y dua-cli. Cuando esas fuentes discrepan, references/precedence.md registra la decisión para que nunca tengas que volver a litigarla.

Paso 1: Establecer contexto (todos los modos)

Haz esto antes de escribir o juzgar cualquier código. Detente e informa si falla una precondición; no adivines alrededor de un toolchain faltante o un manifest faltante.

  1. Encuentra la raíz del crate (el Cargo.toml más cercano). Señala si es un workspace, una biblioteca, un binario o ambos, y si está publicado (publish = false o consumido solo dentro del workspace o a través de FFI significa interno).
  2. Lee primero las reglas propias del proyecto, porque anulan los valores predeterminados de esta habilidad: rustfmt.toml o .rustfmt.toml, clippy.toml, [lints] y [workspace.lints] en Cargo.toml, edition, rust-version (MSRV), rust-toolchain.toml, CONTRIBUTING.md, AGENTS.md o CLAUDE.md, y cualquier AI_POLICY.md. Si AI_POLICY.md o CONTRIBUTING.md restringe contribuciones de IA o agentes, informa al usuario antes de producir cambios destinados a ese repositorio.
  3. Clasifica el código como biblioteca o aplicación. Las reglas de diseño de API son vinculantes para bibliotecas y fuertes recomendaciones para aplicaciones, que deben favorecer la inmediatez sobre la generalidad.
  4. Señala las plataformas. Si rust-toolchain.toml enumera objetivos o el código tiene muchas puertas estilo #[cfg(windows)] para una plataforma diferente de este host, ejecuta la puerta con --target <triple> también (lint y documenta para ese objetivo; las pruebas se saltan). Advertencias como código muerto que aparecen solo en el host debido a puertas de plataforma son artefactos del host, no hallazgos.
  5. Ejecuta scripts/check.sh <crate-root> una vez para registrar la línea base. La necesitas para distinguir tus propias regresiones de deuda preexistente. Usa --features "<lista>" en lugar de --all-features predeterminado cuando el crate tenga características mutuamente excluyentes.

No instales toolchains, componentes o herramientas (nightly, Miri, cargo-hack) y no uses la red más allá de obtener crates a menos que el usuario lo solicite. Cuando una verificación necesite algo que falte, dilo y recomiéndalo.

Paso 2: Elegir el modo

Crear cuando el usuario quiera nuevas funciones, métodos, tipos, módulos o crates. Sigue "Crear código" a continuación.

Modificar cuando el usuario quiera cambiar código existente: una característica, refinamiento, corrección de errores, refactorización o remediación de hallazgos de auditoría. Sigue "Modificar código" a continuación.

Auditar cuando el usuario quiera que se revise, evalúe o verifique código existente, con problemas identificados y arreglos propuestos. Sigue "Auditar código" a continuación. Auditar no cambia el código a menos que el usuario lo solicite; produce hallazgos.

Una solicitud puede abarcar múltiples modos ("audita este módulo y arregla lo que encuentres"). Ejecuta la auditoría primero, informa, luego cambia a modificar para los arreglos.

Reglas no negociables

Estas se aplican en cada modo. El conjunto completo de reglas, con IDs, vive en los archivos de referencia enumerados al final.

  • El formateo es trabajo de rustfmt. Nunca formatee a mano contra rustfmt. Nunca agregue #[rustfmt::skip] excepto para alineación deliberada (tablas, matrices) o código generado.
  • El código es sólido. El código seguro no debe poder causar comportamiento indefinido. Cada bloque unsafe tiene un comentario // SAFETY: directamente encima explicando por qué se cumple cada precondición. Cada unsafe fn y unsafe trait tiene una sección de documentación # Safety. Usa unsafe solo para FFI, una necesidad de rendimiento comparada, o una abstracción novedosa, y nunca para eludir Send, Sync o los lifetimes. Ver references/unsafe.md.
  • Errores versus pánicos. Fallos recuperables causados por la entrada o el entorno devuelven Result (o Option cuando la causa es obvia). Los errores de programación detectados provocan pánico. El código de biblioteca nunca entra en pánico por entrada del llamante que podría ser razonablemente inválida. Ver references/errors.md.
  • Errores de biblioteca permiten que los llamantes ramifiquen sin analizar texto. Un tipo de error concreto con un kind() que devuelve un enum #[non_exhaustive] público, o predicados is_*(). Los campos privados están bien; un kind privado sin acceso es un defecto. Los mensajes apuntan al token ofensivo y la posición, y nunca copian toda la entrada.
  • Sin unwrap() desnudo en código de producción. Usa ?, coincidencia de patrones, o expect("...") cuyo mensaje establece por qué se cumple la invariante. unwrap() está bien en pruebas. Los ejemplos de documentación usan ? con la línea oculta # Ok::<(), Box<dyn std::error::Error>>(()).
  • Cada nueva dependencia es un costo, las dev-dependencies incluidas. Añade una solo cuando elimine complejidad real o proporcione corrección que no puedas escribir razonablemente (el plegado de mayúsculas y minúsculas Unicode es una buena razón; un framework de pruebas de propiedades para un parser de 100 líneas no). Di por qué en tu informe.
  • La estructura coincide con el tamaño. No crees un módulo para una función pequeña y su tipo de error; un módulo se gana su archivo con un concepto distinto y varios elementos o unos cientos de líneas.
  • Las anulaciones de lint usan #[expect(lint, reason = "...")] , no #[allow], para que surjan anulaciones obsoletas.
  • Los elementos públicos están documentados , la primera oración es una línea de unas 15 palabras, y las funciones incluyen secciones # Errors, # Panics, y # Safety siempre que apliquen. Ver references/documentation.md.
  • Los tipos públicos implementan Debug. Los tipos destinados a ser leídos por personas también implementan Display.
  • Los comentarios explican por qué, no qué. Si un comentario repite el código, elimínalo. El comentario del asignador de memoria de ripgrep en crates/core/main.rs es el modelo: decisión, razón y las condiciones bajo las que aplica.
  • Sin diagramas ASCII-art o caracteres de dibujo de cajas en comentarios o documentación. Describe la estructura en oraciones; los dibujos son ilegibles con un lector de pantalla y se pudren cuando el código cambia. (Convención del equipo, no ascendente).
  • Sin contenido de diario de diseño en la documentación. La documentación describe el comportamiento actual, no cómo llegó a ser el código o qué pautas se siguieron.
  • Las pruebas verifican el comportamiento. Sin pruebas que repitan una constante o reflejen las ramas de la implementación.

Crear código

Trabaja de afuera hacia adentro: tipos y firmas primero, luego documentación, luego implementación, luego pruebas. Escribir el comentario de documentación antes del cuerpo es la forma más rápida de descubrir una API confusa.

  1. Ubícalo. Coloca el elemento en el módulo que posee su concepto; en un crate pequeño eso suele ser lib.rs. Los nuevos módulos se nombran según su tipo principal y solo se crean cuando el código lo justifica (ORG-19). Ver references/organization.md.
  2. Modela con tipos. Newtypes para valores que son fáciles de confundir o que llevan invariantes, con constructores que hacen cumplir la invariante. Un enum en lugar de un parámetro bool cuyo significado no es obvio en el lugar de la llamada. Campos nombrados sobre tuplas. Haz que los estados inválidos sean irrepresentables.
  3. Dale forma a la firma. Toma prestado lo que solo lees (&str, &[T], &Path, Option<&T>), toma propiedad solo cuando almacenas o consumes. En bibliotecas, acepta impl AsRef<Path> o impl IntoIterator donde elimine fricción; en aplicaciones, mantén tipos concretos. Builders para tipos con varias opciones opcionales, validando en build(). Ver references/api-design.md.
  4. Nómbralo. Mayúsculas y minúsculas según RFC 430; conversiones as_ / to_ / into_; constructores new, with_*, try_new; getters foo(). Sin palabras comodín (Manager, Service, Factory, Helper, Util), y ningún nombre que colisione con un significado existente en la misma interfaz (NAME-9).
  5. Documéntalo según references/documentation.md, incluyendo un ejemplo ejecutable para elementos públicos, y la unidad de cualquier posición o longitud que devuelvas.
  6. Impleméntalo. Funciones de un solo propósito. Un bucle for simple sobre una cadena de combinadores una vez que la cadena necesita condicionales o estado externo; combinadores cuando reemplacen lógica escrita a mano (any, position, sum). Anotaciones de tipo donde la inferencia dejaría a un lector adivinando. El texto humano obtiene manejo consciente de Unicode: la coincidencia que no distingue mayúsculas y minúsculas usa el plegado de mayúsculas y minúsculas Unicode, o documenta sus lagunas (API-27).
  7. Maneja errores según references/errors.md: en bibliotecas un tipo de error concreto con un kind público o predicados; en aplicaciones anyhow con .context().
  8. Pruébalo según references/testing.md: pruebas unitarias en línea, pruebas de integración bajo tests/, y verificaciones amplias de invariantes que no necesiten nuevas dependencias (enumera entradas cortas, o un bucle con semilla contra una referencia ingenua).
  9. Verifica con la puerta a continuación.

Modificar código

El objetivo es el cambio correcto más pequeño que deje el código tocado al menos tan claro como lo encontraste.

  1. Lee antes de editar. Lee toda la función, sus llamantes, sus pruebas y la API vecina. Identifica convenciones locales (estilo de importación, tipo de error, estilo de encabezado de documentación como # Example versus # Examples, ancho de línea, densidad, nombres de parámetros y claves) y adáptate a ellas, incluso si los valores predeterminados de esta habilidad difieren.
  2. Las correcciones de errores comienzan con una prueba fallida que cubra la clase de error. Reproduce la entrada informada, luego agrega los casos vecinos que la misma causa raíz rompe (más elementos, otros ordenamientos, combinaciones). Míralos fallar, corrige la causa raíz, míralos pasar. Si el proyecto mantiene pruebas de regresión en un solo lugar (tests/regression.rs de ripgrep), añade las tuyas allí.
  3. Corrige la causa, no el síntoma. Un nuevo unwrap_or_default(), clone(), o retorno temprano que silencie un fallo no es una corrección a menos que puedas explicar por qué la ruta original era incorrecta. Pon un comentario de una línea en la corrección si la razón no es obvia a partir del código.
  4. Mantente quirúrgico. No renombres, reordenes ni reformatees código que no se te pidió tocar. Enumera problemas no relacionados para el usuario en lugar de corregirlos en silencio.
  5. Mantén las APIs y ABIs públicas estables a menos que el usuario apruebe un cambio disruptivo. Añadir un campo a una estructura pública con campos públicos, una variante a un enum público exhaustivo, un método de trait requerido, o cambiar un contrato FFI es disruptivo.
  6. Actualiza la documentación y las pruebas con el código. Una firma o comportamiento cambiado significa # Errors, # Panics, ejemplos y pruebas actualizados en el mismo cambio.
  7. Formateo: si la línea base estaba limpia de rustfmt, ejecuta cargo fmt. Si no lo estaba, formatea solo lo que cambiaste e informa al usuario. Si rustfmt.toml usa opciones solo de nightly (rustfmt estable advierte que están "solo disponibles en el canal nightly"), el estándar del proyecto es cargo +nightly fmt; úsalo si está instalado, y de lo contrario no formatees nada automáticamente y dilo, porque rustfmt estable reescribiría el código contra la configuración del proyecto.
  8. Remediación de una auditoría: corrige los hallazgos por orden de gravedad, un hallazgo por cambio lógico, y nombra el hallazgo en tu resumen.
  9. Verifica con la puerta a continuación y confirma que no introdujiste nuevas advertencias en relación con la línea base, en cada objetivo que verificaste en el paso 1.

Auditar código

  1. Ejecuta scripts/check.sh --audit <crate-root> (más --target según el paso 1). El pase --audit informa, con accesibilidad de API pública, unsafe no documentado, documentación faltante y secciones # Errors/# Panics, unwrap fuera de pruebas, #[allow] sin razón, dbg!/todo!, importaciones glob, y aserciones sin mensajes. Informa estos resultados de higiene de manera compacta: un hallazgo Minor por categoría (documentación, Debug, comentarios SAFETY, configuración de lint), cada uno con un conteo y los pocos casos que más importan. Un paso de puerta que falla solo porque el toolchain aquí es más nuevo que el que el CI del proyecto o rust-toolchain.toml usa es deriva del toolchain: un hallazgo Minor, no un Major.

  2. Ejecuta python3 -I scripts/audit_scan.py <crate-root> para lo que clippy no puede ver: reexportaciones glob, nombres de tipo comodín, comentarios ASCII-art, documentación de historial de diseño, tablas de parámetros, TODOs desnudos, mensajes expect vacíos, y macros de impresión en código de biblioteca. Confirma cada acierto leyendo el código; descarta falsos positivos.

  3. Sondea el comportamiento como lo encuentran los usuarios. Aquí es donde se encuentran la mayoría de los errores visibles para el usuario en crates reales, así que dedica la mayor parte de la auditoría aquí y en el paso 5. Lee la documentación, especificación y pruebas del crate para enumerar las características de entrada que afirma manejar. Para cada una, construye una entrada realista pequeña que las pruebas existentes no cubran, ejecútala a través de la API pública desde un crate desechable fuera del workspace, y compara la salida con lo que un usuario debería obtener. Cubre las características que el formato permite pero los fixtures omiten:

    • valores heredados, indirectos o predeterminados
    • duplicados
    • partes opcionales u ocultas
    • daño leve que otras herramientas toleran
    • texto no ASCII y codificaciones heredadas
    • tamaños grandes pero legítimos

    Informa cada problema confirmado con la entrada que lo muestra.

  4. Aprovecha la entrada no confiable. Para cada función pública que analice bytes o texto no confiables, aliméntala con cada entrada corta sobre un alfabeto relevante o unos pocos millones de mutaciones aleatorias con semilla, y detecta pánicos. También prueba estructuras elaboradas que hacen que el trabajo crezca más rápido que el tamaño de la entrada (referencias compartidas o recursivas, anidamiento profundo) bajo un tiempo de espera.

  5. Lee el código para lo que las herramientas no pueden juzgar: solidez de cada bloque unsafe, diseño de errores, forma de la API, límites de módulos, nomenclatura, calidad de las pruebas, y si los comentarios explican por qué. En código que se comunica con el sistema operativo, también verifica:

    • pánicos en una syscall, fallo de E/S o entorno (assert! o unwrap en un valor de retorno, una variable de entorno no UTF-8 o campo passwd)
    • código entre fork y exec (cierres pre_exec) o en un manejador de señal que asigna, bloquea, formatea, registra o sale, nada de lo cual es seguro para async-signal
    • descriptores de archivo o manejadores filtrados, y señales enviadas a un ID de proceso que puede haber sido recolectado y reutilizado
    • conversiones de estrechamiento y aritmética no verificada en tamaños, conteos y coordenadas

    Usa references/audit-checklist.md.

  6. Informa usando el formato a continuación. Propón una corrección concreta para cada hallazgo.

Los pasos 1 y 2 son un piso rápido, no la auditoría: no dediques más de aproximadamente una quinta parte del tiempo en ellos. Una auditoría que enumere principalmente lint, documentación y s...

Skills relacionados