ansible-automation-eng…
Ansible automation: playbooks, roles, collections, Molecule testing, Vault security.
Load this file before you write or edit any Go code. Each rule below fixes a failure measured in generated code: code that built and passed its tests but used outdated or weak idioms. Rules marked with a version need that version or later in `go.mod`; check the `go` line first.
$ 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 Go code. Each rule below fixes a failure measured in generated code: code that built and passed its tests but used outdated or weak idioms. Rules marked with a version need that version or later in `go.mod`; check the `go` line first.
Load this file before you write or edit any Go code. Each rule below fixes a failure measured in generated code: code that built and passed its tests but used outdated or weak idioms. Rules marked with a version need that version or later in `go.mod`; check the `go` line first.
grep '^go ' go.mod # "go 1.27" unlocks every rule here; lower versions: see go-version-idioms.md
Every exported type, function, method, constant block, and variable block gets a comment that starts with its name. Exactly one non-test file per package starts with a package comment directly above the `package` line; `package main` gets one too. Measured: 10 of 12 unguided outputs skipped doc comments; 6 of 14 guided outputs still skipped the package comment.
// BAD
package userrepo
type Repo struct{ db *sql.DB }
func New(db *sql.DB) *Repo { return &Repo{db: db} }
// GOOD
// Package userrepo stores users in SQLite through database/sql.
package userrepo
// Repo stores users in SQLite. It is safe for concurrent use.
type Repo struct{ db *sql.DB }
// New returns a Repo that uses db. The caller owns db and closes it.
func New(db *sql.DB) *Repo { return &Repo{db: db} }State concurrency safety, ownership, and zero-value behavior when they matter.
| Do | Not | Since | |----|-----|-------| | `errors.Is(err, io.EOF)`, `errors.Is(err, flag.ErrHelp)`, `errors.Is(err, sql.ErrNoRows)` | `err == io.EOF`, `err == flag.ErrHelp` | 1.13 | | `if e, ok := errors.AsType[*http.MaxBytesError](err); ok {` | `var e *http.MaxBytesError; if errors.As(err, &e) {` | 1.26 | | Sentinels prefixed with the package: `errors.New("userrepo: not found")` | `errors.New("not found")` | - | | Name the package once per message: `fmt.Errorf("create user %q: %w", email, ErrDuplicateEmail)` | `fmt.Errorf("userrepo: create: %w", ErrDuplicateEmail)` (prints `userrepo: create: userrepo: duplicate email`) | - | | Named constants from the driver: `sqlite3.SQLITE_CONSTRAINT_UNIQUE` | Magic numbers: `e.Code() == 2067` | - | | Match a driver's typed error or code | `strings.Contains(err.Error(), "UNIQUE constraint failed")` | - |
Tests use `errors.AsType` too:
se, ok := errors.AsType[*filter.SyntaxError](err)
if !ok {
t.Fatalf("error %T is not *SyntaxError", err)
}Typed driver errors: find the type in the module cache, then match it. Example for `modernc.org/sqlite` (verified in v1.59.0 source: `*sqlite.Error` has `Code() int`; codes live in `modernc.org/sqlite/lib`):
import (
"modernc.org/sqlite"
sqlite3 "modernc.org/sqlite/lib"
)
func isUniqueViolation(err error) bool {
e, ok := errors.AsType[*sqlite.Error](err)
return ok && e.Code() == sqlite3.SQLITE_CONSTRAINT_UNIQUE
}For other drivers, read the source first: `grep -rn 'func (e \*Error)' $(go env GOMODCACHE)/<driver>@<version>/`.
Wrap with context that names the operation and the input: `fmt.Errorf("create user %q: %w", email, err)`. Return an error unchanged when the callee already says enough.
`os.Exit` skips deferred calls. Never `defer` in a function that calls `os.Exit`; move the work into a function that returns an exit code. Measured: every unguided CLI `main` did this.
// BAD: stop never runs
func main() {
ctx, stop := signal.NotifyContext(context.Background(), os.Interrupt, syscall.SIGTERM)
defer stop()
os.Exit(wordfreq.Run(ctx, os.Args[1:], os.Stdin, os.Stdout, os.Stderr))
}
// GOOD
func main() {
os.Exit(run())
}
func run() int {
ctx, stop := signal.NotifyContext(context.Background(), os.Interrupt, syscall.SIGTERM)
defer stop()
return wordfreq.Run(ctx, os.Args[1:], os.Stdin, os.Stdout, os.Stderr)
}`wg.Go(f)` replaces `wg.Add(1); go func() { defer wg.Done(); ... }()` (1.25). Use it in library code and in tests. `for range n` replaces `for i := 0; i < n; i++` when `i` is unused (1.22). Loop variables are per-iteration since 1.22: delete `i := i` and `tt := tt` copies and closure parameters that only pass the loop variable.
Canonical bounded worker pool. Results go straight into a preallocated slice by index; no results channel, no dispatcher goroutine, at most `workers` goroutines:
// Map calls fn for every item with at most workers calls in flight and
// returns the results in input order.
func Map[T, R any](ctx context.Context, items []T, workers int, fn func(context.Context, T) (R, error)) ([]R, error) {
if workers < 1 {
return nil, errors.New("pool: workers must be >= 1")
}
ctx, cancel := context.WithCancelCause(ctx)
defer cancel(nil)
out := make([]R, len(items))
var next atomic.Int64
var wg sync.WaitGroup
for range min(workers, len(items)) {
wg.Go(func() {
for ctx.Err() == nil {
i := int(next.Add(1) - 1)
if i >= len(items) {
return
}
r, err := fn(ctx, items[i])
if err != nil {
cancel(fmt.Errorf("item %d: %w", i, err)) // first call wins
return
}
out[i] = r // each index written by one goroutine: no race
}
})
}
wg.Wait()
if err := context.Cause(ctx); err != nil { // fn error, or parent's context.Canceled
return nil, err
}
return out, nil
}Every goroutine you start has an owner that waits fo
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.
Repo: notque/vexjoy-agent
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 **Version range**:…
**Scope**: Molecule test scenarios, ansible-lint rules, idempotency validation, and check-mode patterns **Version range**: Molecule 6.0+ / ansible-lint 6.0+ /…
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 to detect and how to fix…
Zero-dependency combat visual upgrades: CSS particle replacement, Framer Motion combat juice, CSS 3D card transforms.