ansible-automation-eng…
Ansible automation: playbooks, roles, collections, Molecule testing, Vault security.
Version-pinned idiom table, hard gates, and error-message-to-version map. Check `Cargo.toml` before applying any row: writing a 1.75+ idiom on a project with `rust-version = "1.65"` fails the MSRV check. For how to write each idiom in context (with before/after code), load
$ 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.
Version-pinned idiom table, hard gates, and error-message-to-version map. Check `Cargo.toml` before applying any row: writing a 1.75+ idiom on a project with `rust-version = "1.65"` fails the MSRV check. For how to write each idiom in context (with before/after code), load
Version-pinned idiom table, hard gates, and error-message-to-version map. Check `Cargo.toml` before applying any row: writing a 1.75+ idiom on a project with `rust-version = "1.65"` fails the MSRV check. For how to write each idiom in context (with before/after code), load [rust-modern-code.md](rust-modern-code.md).
grep -E '^edition|^rust-version' Cargo.toml # "rust-version = "1.85"" means 1.85 features are available; lower versions: see table below
The `rust-version` field in `Cargo.toml`, not the installed toolchain, decides what compiles during `cargo check --all`. A 1.85 toolchain building a crate with `rust-version = "1.75"` rejects 1.76+ language features.
The most common AI-generated Rust failure mode is old idioms where modern ones exist:
| Outdated Pattern | Modern Replacement | Since | |-----------------|-------------------|-------| | `Box<dyn std::error::Error>` as library return | `thiserror`-derived error type | stable | | `impl From<E> for MyError` by hand | `#[from]` attribute in `thiserror` | stable | | `if let Some(x) = opt { return Err(...); }` | `let Some(x) = opt else { return Err(...); }` (let-else) | 1.65 | | `match result { Ok(v) => v, Err(e) => return Err(e) }` | `?` operator | 1.13 | | Custom iterator struct with `Iterator` impl | `gen { yield item; }` block | 1.85 (2024 edition) | | `async fn` in trait via `async-trait` macro | `async fn` in trait (stable) | 1.75 | | `Box<dyn Future<Output = T> + Send>` return from trait | `-> impl Future<Output = T>` in impl (RPITIT) | 1.75 | | `dyn Error + Send + Sync + 'static` box | `anyhow::Error` in application code | stable | | `eprintln!("{}", e); process::exit(1)` in main | `fn main() -> anyhow::Result<()>` | stable | | `serde_json::from_str(s).unwrap()` | `serde_json::from_str(s).context("parse foo")?` | stable | | `String` parameter in public API | `impl AsRef<str>` or `&str` | stable | | `Vec<T>` parameter that is only iterated | `impl IntoIterator<Item = T>` or `&[T]` | stable | | `Arc<Mutex<T>>` in async code | `Arc<tokio::sync::Mutex<T>>` | tokio stable | | `thread::sleep` in async tests | `tokio::time::pause()` + `tokio::time::advance(d)` | tokio stable | | `for i in 0..items.len() { let item = &items[i]; }` | `for item in &items { }` | stable | | Manual `sort_by_key` with allocation | `.sort_by(|a, b| a.key.cmp(&b.key))` | stable | | `unwrap_or_else(|_| default)` for infallible | `unwrap_or(default)` | stable | | `if x.is_some() { x.unwrap() }` | `if let Some(v) = x { v }` or `x?` in Result context | stable | | `HashMap::new()` + manual inserts in tests | `HashMap::from([("k", "v")])` | 1.56 | | Derive `Clone` + manual `new` for builder | `bon` or `derive_builder` crate | stable | | `futures::future::join_all(vec)` | `tokio::task::JoinSet` | tokio 1.x | | `tokio::spawn` drop (fire-and-forget) | Store `JoinHandle`, call `.await` on shutdown | stable |
Notes on the newest rows:
Framework: `skills/shared-patterns/forbidden-patterns-template.md`.
| Pattern | Why blocked | Fix | |---------|-------------|-----| | `.unwrap()` in library code | Panics with no recovery path for the caller | Return `Err(...)` or `.ok_or_else(...)` | | `.expect("")` (empty string message) | Panic with no diagnostic context | `.expect("user id must be set at this point")` | | `.clone()` to satisfy the borrow checker | Hides a design flaw; costs allocation | Restructure ownership or use `Arc` / `Rc` explicitly | | `let _ = result;` / `let _ = tx.send(...)` | Silently discards errors | `result?` or `result.ok()` with explicit intent | | `err.to_string().contains("...")` | Breaks when messages change | `downcast_ref::<ConcreteError>()` or `matches!(err, MyError::Variant)` | | `std::thread::sleep` in async code | Blocks the executor thread | `tokio::time::sleep(d).await` | | `std::sync::Mutex` held across `.await` | Deadlocks under async | `tokio::sync::Mutex` | | Fire-and-forget `tokio::spawn` (dropped `JoinHandle`) | Panics lost; no shutdown path | Store `JoinHandle`; await on shutdown | | `Box<dyn std::error::Error>` in library API | Erases error type; callers cannot match variants | `thiserror`-derived enum |
grep -rn "\.unwrap()" --include="*.rs" | grep -v "_test\|#\[test\]\|mod tests"
grep -rn '\.expect("")' --include="*.rs"
grep -rn 'let _ = ' --include="*.rs"
grep -rn 'to_string().*contains\|contains.*to_string()' --include="*.rs"
grep -rn 'std::thread::sleep' --include="*.rs"Sanctioned exceptions:
| Error Message | Root Cause | Fix | |---------------|------------|-----| | `error[E0658]: let chains are experimental` | Rust < 1.88 | Use nested `if let` or upgrade MSRV | | `error[E0658]: use of unstable library feature 'let_else'` | Rust < 1.65 | Upgrade to 1.65+ | | `error[E0277]: the trait bound ... is not satisfied` on async trait | Rust < 1.75 without `async-trait` | Add `#[async_trait]` or upgrade to 1.75 | | `error[E0562]: 'impl Trait' only allowed in ... not in return type of trait methods` | Rust < 1.75 (RPITIT) | Upgrade to 1.75 or u
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.