Improve AGENTS guide for Ansible coding workflows

This commit is contained in:
Fabio Scotto di Santolo
2026-03-16 22:53:07 +01:00
parent 5e4fa3e552
commit 2d6b622378

126
AGENTS.md
View File

@@ -1,16 +1,16 @@
# AGENTS.md # AGENTS.md
Agent guide for this repository. Guidance for coding agents working in this repository.
Project type: Ansible infrastructure with managed dotfiles. Project type: Ansible infrastructure + managed dotfiles.
## Scope and layout ## Repository scope and layout
- Entry playbook: `ansible/site.yml` - Entry playbook: `ansible/site.yml`
- Inventory: `ansible/inventory/hosts.yml` - Inventory: `ansible/inventory/hosts.yml`
- Group vars: `ansible/inventory/group_vars/*.yml` - Group vars: `ansible/inventory/group_vars/*.yml`
- Host vars: `ansible/inventory/host_vars/*.yml` - Host vars: `ansible/inventory/host_vars/*.yml`
- Roles: `ansible/roles/*/tasks/main.yml` - Roles: `ansible/roles/*/tasks/main.yml`
- Dotfiles source: `dotfiles/` - Dotfiles source of truth: `dotfiles/`
- Ansible config: `ansible.cfg` - Ansible config file: `ansible.cfg`
Current `ansible.cfg` defaults: Current `ansible.cfg` defaults:
- `inventory = ansible/inventory/hosts.yml` - `inventory = ansible/inventory/hosts.yml`
@@ -18,17 +18,17 @@ Current `ansible.cfg` defaults:
- `host_key_checking = False` - `host_key_checking = False`
- `retry_files_enabled = False` - `retry_files_enabled = False`
## Cursor and Copilot instructions ## Local instruction files (Cursor/Copilot)
Checked in this repo and not found: As of now, these files are not present:
- `.cursorrules` - `.cursorrules`
- `.cursor/rules/` - `.cursor/rules/`
- `.github/copilot-instructions.md` - `.github/copilot-instructions.md`
If any of these are added later, treat them as higher-priority local instructions. If any appear later, treat them as higher-priority local instructions.
## Build, lint, and test commands ## Build, lint, and test commands
There is no compile/build artifact in this repo. There is no compile/build artifact in this repo.
Validation is done with syntax checks, dry-runs, inventory checks, and linting. Validation is performed with syntax checks, dry-runs, inventory checks, and linting.
Main apply run: Main apply run:
```bash ```bash
@@ -49,6 +49,7 @@ Inventory sanity checks:
```bash ```bash
ansible-inventory --graph ansible-inventory --graph
ansible-inventory --list ansible-inventory --list
ansible all --list-hosts
``` ```
Linting (if installed): Linting (if installed):
@@ -59,102 +60,99 @@ yamllint ansible/
``` ```
## Single-test equivalents (important) ## Single-test equivalents (important)
There is no dedicated test harness (no Molecule/pytest suite). There is no Molecule/pytest test suite in this repo.
Use these as targeted single-test workflows: Use these targeted checks as "single test" workflows.
Syntax-check only: Syntax-only check:
```bash ```bash
ansible-playbook ansible/site.yml --syntax-check ansible-playbook ansible/site.yml --syntax-check
``` ```
Dry-run one host (best single test): Best single-host safety test:
```bash ```bash
ansible-playbook ansible/site.yml --limit nymph --check --diff ansible-playbook ansible/site.yml --limit nymph --check --diff
``` ```
Start from one known task name: Start from one known task:
```bash ```bash
ansible-playbook ansible/site.yml --limit ikaros --start-at-task "Copy .bashrc" --check --diff ansible-playbook ansible/site.yml --limit ikaros --start-at-task "Copy common dotfiles" --check --diff
``` ```
Run one role by task boundary (practical approximation): Role-boundary approximation:
```bash ```bash
ansible-playbook ansible/site.yml --limit ikaros --start-at-task "Install Void nonfree repository if needed" --check --diff ansible-playbook ansible/site.yml --limit ikaros --start-at-task "Install Void nonfree repository if needed" --check --diff
``` ```
List hosts targeted by current inventory:
```bash
ansible all --list-hosts
```
Notes: Notes:
- `--tags` is preferred for targeted runs once tasks are tagged consistently. - Current active stack in `site.yml`: `dotfiles_common`, `packages_void`, `services_runit`, `profile_desktop_i3`.
- Today, `site.yml` actively applies `dotfiles_common`, `packages_void`, `services_runit`, and `profile_desktop_i3`. - Use `--tags` for targeted runs when tags are available.
- Dependencies: Python 3, Ansible, and host access (local or SSH depending on inventory). - Minimum dependencies: Python 3, Ansible, host access (local or SSH).
- Setup: `python3 -m pip install ansible` (plus optional `ansible-lint yamllint`). - Setup example: `python3 -m pip install ansible`.
## Code style guidelines ## Code style guidelines
### Core principles ### Core principles
- Keep automation idempotent, declarative, and host-safe. - Prefer idempotent, declarative, host-safe automation.
- Preserve variable layering: `all -> OS -> profile -> host`. - Preserve layering: `all -> OS -> profile -> host`.
- Keep edits minimal and local; avoid opportunistic refactors. - Keep edits minimal and scoped to user intent.
- Prefer readability over compression in YAML/Jinja. - Avoid speculative refactors unrelated to the requested change.
- Optimize for readability over clever Jinja/YAML compression.
### Modules, imports, and role structure ### Modules, imports, and task structure
- Use FQCN modules (`ansible.builtin.copy`, `community.general.xbps`). - Use FQCN modules (`ansible.builtin.copy`, `community.general.xbps`).
- Prefer modules over `ansible.builtin.shell`/`ansible.builtin.command`. - Prefer modules over `ansible.builtin.command`/`ansible.builtin.shell`.
- If command/shell is necessary, document intent via task name and guards. - Use `command`/`shell` only when no module fits; explain intent in task name.
- Keep `ansible/site.yml` orchestration-focused; implementation belongs in roles. - When using `command`/`shell`, set `changed_when` and `failed_when` as needed.
- Split large role task files with `import_tasks`/`include_tasks`. - Keep `ansible/site.yml` orchestration-only; implementation belongs in roles.
- Keep each role narrow in purpose (packages, services, profile, dotfiles). - Keep roles focused by domain (packages, services, profile, dotfiles).
- Split large task files with `import_tasks`/`include_tasks`.
### YAML formatting ### YAML formatting and file hygiene
- Start YAML files with `---`. - Start YAML documents with `---`.
- Use 2-space indentation, never tabs. - Use 2-space indentation; never tabs.
- Keep key ordering stable and meaningful. - Keep key ordering stable and meaningful.
- Quote file modes as strings: `"0644"`, `"0755"`, `"0600"`, `"0700"`. - Quote file modes as strings (`"0644"`, `"0755"`, `"0600"`, `"0700"`).
- Keep long Jinja expressions multiline. - Use multiline Jinja for long expressions.
- Avoid trailing whitespace. - Avoid trailing whitespace and noisy reformatting.
### Variables and types ### Variables, types, and templating
- Use `snake_case` variable names. - Use `snake_case` variables.
- Use semantically scoped names (`common_packages`, `void_packages_base`, `host_packages`). - Use semantically scoped names (`common_packages`, `void_packages_base`, `host_packages`).
- Keep booleans as `true`/`false`, not quoted strings. - Keep booleans as real booleans (`true`/`false`), not quoted strings.
- Keep lists and dicts as real YAML collections. - Keep lists/maps as YAML collections, not comma-separated strings.
- Use `default([])` / `default({})` for optional variables. - Use guards for optional values: `default([])`, `default({})`.
- Build paths consistently from `{{ user_home }}` and related vars. - Build home-relative paths from `{{ user_home }}` consistently.
- Put shared defaults in `group_vars/all.yml`; specialize in group/host vars. - Put shared defaults in `group_vars/all.yml`; specialize in group/host vars.
### Naming conventions ### Naming conventions
- Role directories: lowercase with underscores. - Role directory names: lowercase with underscores.
- Task names: imperative and outcome-based (`Enable host runit services`). - Task names: imperative and outcome-based.
- Inventory group names and matching var filenames should stay aligned. - Keep inventory group names and var file names aligned.
- Host var filenames must match hostnames exactly. - Host var filenames must match hostnames exactly.
### Error handling and safety ### Error handling and safety
- Guard OS/profile-specific steps with `when`. - Guard OS/profile-specific behavior with `when`.
- Use explicit `loop` inputs and default guards for optional lists. - Prefer explicit `loop` inputs; avoid implicit assumptions.
- For `command`/`shell`, define `changed_when` and `failed_when` when needed. - Do not suppress failures without a clear operational reason.
- Do not suppress failures unless there is a clear operational reason.
- Validate risky changes with `--check --diff` before full apply. - Validate risky changes with `--check --diff` before full apply.
- Avoid destructive file operations in user homes unless explicitly required. - Avoid destructive operations in user homes unless explicitly required.
- Avoid touching secrets material; never commit credentials. - Never commit credentials or contents from `secrets/`.
### Dotfiles and shell scripts ### Dotfiles and shell script style
- Prefer POSIX `sh`; use Bash only when required. - Prefer POSIX `sh`; use Bash only when required.
- If Bash is required, use shebang `#!/usr/bin/env bash`. - Bash scripts should use `#!/usr/bin/env bash`.
- Quote expansions (`"$var"`) unless intentional splitting is required. - Quote expansions (`"$var"`) unless intentional splitting is required.
- Keep scripts non-interactive when invoked by automation. - Keep scripts non-interactive when run by automation.
- Preserve executable bits on scripts copied with `mode: preserve`.
## Agent expectations ## Agent workflow expectations
- Do not modify unrelated files. - Do not modify unrelated files.
- Never commit or expose data from `secrets/`. - Verify assumptions by reading inventory, vars, and active roles before editing.
- Keep `AGENTS.md` and `README.md` in sync with workflow changes. - Keep AGENTS and README aligned when workflow or commands change.
- When adding new role domains, add tags to support targeted execution. - When adding new domains/roles, also add tagging and validation guidance.
## Pre-merge checklist ## Pre-merge checklist
Run before submitting changes: Run before proposing or finalizing changes:
```bash ```bash
ansible-playbook ansible/site.yml --syntax-check ansible-playbook ansible/site.yml --syntax-check
ansible-playbook ansible/site.yml --check --diff --limit <host> ansible-playbook ansible/site.yml --check --diff --limit <host>