ansible-automation-eng…
Ansible automation: playbooks, roles, collections, Molecule testing, Vault security.
Load this file before you write or edit any Rust code. Each rule below fixes a failure measured in generated code: code that compiled and passed its tests but used outdated or weak idioms. Rules marked with a version need that version or later in `Cargo.toml`; check the
$ npx -y skills add notque/vexjoy-agent --agent claude-codeHow it fires
How this agent gets triggered: by you, by Claude, or both.
Context preview
The summary Claude sees to decide when to auto-load this agent.
Load this file before you write or edit any Rust code. Each rule below fixes a failure measured in generated code: code that compiled and passed its tests but used outdated or weak idioms. Rules marked with a version need that version or later in `Cargo.toml`; check the
Load this file before you write or edit any Rust code. Each rule below fixes a failure measured in generated code: code that compiled and passed its tests but used outdated or weak idioms. Rules marked with a version need that version or later in `Cargo.toml`; check the `edition` and `rust-version` lines first.
grep -E '^edition|^rust-version' Cargo.toml # "edition = "2024"" unlocks every rule here; lower editions: see rust-version-idioms.md
Every public type, function, method, constant, and module gets a doc comment that starts with a verb or noun phrase describing what the item does (not just repeating its name). Every `lib.rs` and `mod.rs` starts with a `//!` crate or module doc comment. Measured: 9 of 12 unguided outputs skipped doc comments; 5 of 14 guided outputs still skipped the module comment.
// BAD
pub struct UserRepo {
pool: sqlx::PgPool,
}
impl UserRepo {
pub fn new(pool: sqlx::PgPool) -> Self {
Self { pool }
}
}
// GOOD
//! User repository backed by PostgreSQL via sqlx.
/// Stores users in PostgreSQL. Safe for concurrent use via internal connection pooling.
pub struct UserRepo {
pool: sqlx::PgPool,
}
impl UserRepo {
/// Creates a `UserRepo` using the given connection pool. The caller owns and closes the pool.
pub fn new(pool: sqlx::PgPool) -> Self {
Self { pool }
}
}State thread-safety, ownership, and zero-value/default behavior when they matter.
| Do | Not | Since | |----|-----|-------| | `thiserror` for library error types | `Box<dyn Error>` or `String` as error return in library code | stable | | `anyhow::Result` / `.context("...")` for application code | `.unwrap()` or `.expect("")` outside tests | stable | | `err.downcast_ref::<ConcreteError>()` / `err.is::<E>()` (anyhow) | String matching: `err.to_string().contains("not found")` | stable | | Named variants: `Error::NotFound { id }` | `Error::NotFound(String)` with formatted text as data | stable | | `.context("create user {email:?}")` to add call-site context | Empty wrappers: `anyhow!("error: {e}")` that repeat the message | stable | | Driver typed errors via `sqlx::Error::Database` downcast | Magic codes or string matching on SQLSTATE | stable |
Library errors with `thiserror`:
// BAD
pub fn get_user(id: Uuid) -> Result<User, Box<dyn std::error::Error>> { ... }
// GOOD
use thiserror::Error;
#[derive(Debug, Error)]
pub enum UserError {
#[error("user {id} not found")]
NotFound { id: Uuid },
#[error("database error")]
Database(#[from] sqlx::Error),
}
pub async fn get_user(id: Uuid, pool: &PgPool) -> Result<User, UserError> { ... }Application code with `anyhow`:
// BAD
fn load_config(path: &str) -> Result<Config, Box<dyn Error>> {
let s = std::fs::read_to_string(path)?;
Ok(toml::from_str(&s)?)
}
// GOOD
use anyhow::{Context, Result};
fn load_config(path: &str) -> Result<Config> {
let s = std::fs::read_to_string(path)
.with_context(|| format!("read config from {path:?}"))?;
toml::from_str(&s).context("parse config")
}Driver errors — find the typed error in the crate source, then match it:
fn is_unique_violation(err: &sqlx::Error) -> bool {
if let sqlx::Error::Database(db_err) = err {
db_err.is_unique_violation()
} else {
false
}
}// BAD: fire-and-forget, panic lost, no shutdown path
fn start_background_task() {
tokio::spawn(async { do_work().await });
}
// GOOD: tracked handle, can be awaited on shutdown
pub struct Worker {
handle: tokio::task::JoinHandle<()>,
}
impl Worker {
pub fn start() -> Self {
Self {
handle: tokio::spawn(async { do_work().await }),
}
}
pub async fn shutdown(self) {
self.handle.await.expect("worker panicked");
}
}`main` delegates to `run`:
// BAD: unwrap in main, no graceful error display
#[tokio::main]
async fn main() {
run().await.unwrap();
}
// GOOD
#[tokio::main]
async fn main() -> anyhow::Result<()> {
run().await
}
async fn run() -> anyhow::Result<()> {
let config = load_config("config.toml")?;
// ... defers and signal setup here
Ok(())
}Use `tokio::task::JoinSet` for a bounded pool that collects results. Results go back in completion order; use a preallocated `Vec` indexed by task ID when order matters.
/// Map calls fn for every item with at most `workers` tasks in flight.
/// Returns results in the order tasks complete, not input order.
pub async fn map_concurrent<T, R, F, Fut>(
items: Vec<T>,
workers: usize,
f: F,
) -> anyhow::Result<Vec<R>>
where
T: Send + 'static,
R: Send + 'static,
F: Fn(T) -> Fut + Clone + Send + 'static,
Fut: Future<Output = anyhow::Result<R>> + Send,
{
use tokio::task::JoinSet;
let semaphore = Arc::new(tokio::sync::Semaphore::new(workers));
let mut set = JoinSet::new();
for item in items {
let sem = semaphore.clone();
let f = f.clone();
set.spawn(async move {
let _permit = sem.acquire().await?;
f(item).await
});
}Essays and writing behind this toolkit live at vexjoy.com. VexJoy Agent connects plain-English requests to specialist agents, skills, and workflows. /do selects the knowledge and tools needed for your task.
Ansible automation: playbooks, roles, collections, Molecule testing, Vault security.
**Scope**: Module selection patterns, builtin vs command/shell decisions, collection modules, and version-specific module changes…
**Scope**: Molecule test scenarios, ansible-lint rules, idempotency validation, and check-mode patterns **Version range**:…
Universal rules injected by /do at dispatch. Each agent's .md file supplies domain rules.
**Scope**: Failure modes in agent output style — over-reporting, self-congratulation, verbose narration, and hedging. Covers what…
Zero-dependency combat visual upgrades: CSS particle replacement, Framer Motion combat juice, CSS 3D card transforms.