Update agent guidance for current desktop workflow

This commit is contained in:
Fabio Scotto di Santolo
2026-03-28 15:54:16 +01:00
parent e0a2268b83
commit 7a5d3338a0

113
AGENTS.md
View File

@@ -1,85 +1,85 @@
# AGENTS.md # AGENTS.md
Guidance for coding agents working in this repository. Guidance for coding agents working in this repository.
Project type: Ansible-driven infrastructure, workstation/server provisioning, and user dotfiles. Project type: Ansible-driven infrastructure, workstation/server provisioning, and user dotfiles.
## Repository Map ## Repository Map
- Entry playbook: `ansible/site.yml` - Entry playbook: `ansible/site.yml`
- Inventory: `ansible/inventory/hosts.yml` - Inventory: `ansible/inventory/hosts.yml`
- Shared vars: `ansible/inventory/group_vars/*.yml` - Group vars: `ansible/inventory/group_vars/*.yml`
- Host overrides: `ansible/inventory/host_vars/*.yml` - Host vars: `ansible/inventory/host_vars/*.yml`
- Roles: `ansible/roles/*` - Roles: `ansible/roles/*`
- Role assets: `ansible/roles/*/{tasks,templates,files,handlers}/`
- Templates: `ansible/templates/**/*.j2` - Templates: `ansible/templates/**/*.j2`
- Dotfiles: `dotfiles/` - Dotfiles: `dotfiles/`
- Scripts: `scripts/` - Scripts: `scripts/`
- Local secrets area: `secrets/` - Secrets: `secrets/`
## Active Topology
## Topology And Orchestration
- Void desktops: `ikaros`, `nymph` - Void desktops: `ikaros`, `nymph`
- Ubuntu workstation: `deadalus` - Ubuntu workstation: `deadalus`
- Ubuntu server: `prometheus` - Ubuntu server: `prometheus`
- Most hosts currently use `ansible_connection: local` - Most hosts use `ansible_connection: local`
## Active Orchestration
`ansible/site.yml` currently applies:
- `all -> dotfiles_common` - `all -> dotfiles_common`
- `void -> packages_void, services_runit, profile_desktop_i3` - `void -> packages_void, services_runit, profile_desktop_i3`
- `ubuntu_workstation -> packages_ubuntu, services_systemd, profile_workstation_gnome` - `ubuntu_workstation -> packages_ubuntu, services_systemd, profile_workstation_gnome`
- `ubuntu_server -> packages_ubuntu, services_systemd, profile_server` - `ubuntu_server -> packages_ubuntu, services_systemd, profile_server`
- Present but unwired roles: `base`, `dotfiles`
Roles present but not wired into `ansible/site.yml`:
- `base`
- `dotfiles`
## Local Instruction Files ## Local Instruction Files
Checked when this file was updated: Checked when this file was updated:
- `.cursorrules`: not present - `.cursorrules`: not present
- `.cursor/rules/`: not present - `.cursor/rules/`: not present
- `.github/copilot-instructions.md`: not present - `.github/copilot-instructions.md`: not present
If any appear later, treat them as higher-priority repo-local instructions. If any appear later, treat them as higher-priority repo-local instructions.
## Working Principles ## Working Principles
- Preserve the layering: `all -> OS -> profile -> host` - Preserve the layering: `all -> OS -> profile -> host`
- Prefer minimal, targeted edits over cleanup refactors - Prefer minimal, targeted edits over broad cleanup
- Preserve idempotency and reproducibility - Preserve idempotency and reproducibility
- Validate on one limited host before broad rollout - Validate on one limited host before broad rollout
- Treat `secrets/` as sensitive and never print secret values - Treat `secrets/` as sensitive; never print secret values
- Avoid editing vendored code under `dotfiles/common/.tmux/plugins/` unless explicitly asked - Avoid editing vendored code under `dotfiles/common/.tmux/plugins/` unless explicitly asked
- Keep `ansible/site.yml` small; orchestration belongs there, implementation belongs in roles
## Build, Lint, And Test Commands ## Build, Lint, And Test Commands
There is no compile/build pipeline. Confidence comes from syntax checks, dry runs, linting, and targeted script validation. There is no compile/build pipeline. Confidence comes from syntax checks, dry runs, linting, and targeted script validation.
Install tooling if needed: Install tooling if needed:
```bash ```bash
python3 -m pip install ansible ansible-lint yamllint python3 -m pip install ansible ansible-lint yamllint
ansible-galaxy collection install community.general ansible-galaxy collection install community.general
``` ```
Core validation: Core validation:
```bash ```bash
ansible-playbook ansible/site.yml --syntax-check ansible-playbook ansible/site.yml --syntax-check
ansible-playbook ansible/site.yml --limit deadalus --check --diff
ansible-playbook ansible/site.yml --limit prometheus --check --diff
ansible-playbook ansible/site.yml --limit ikaros --check --diff ansible-playbook ansible/site.yml --limit ikaros --check --diff
ansible-playbook ansible/site.yml --limit nymph --check --diff ansible-playbook ansible/site.yml --limit nymph --check --diff
``` ansible-playbook ansible/site.yml --limit deadalus --check --diff
Linting and script checks: ansible-playbook ansible/site.yml --limit prometheus --check --diff
```bash
ansible-lint ansible/site.yml ansible-lint ansible/site.yml
ansible-lint ansible/roles ansible-lint ansible/roles
yamllint ansible/ yamllint ansible/
sh -n scripts/bootstrap_mail.sh
shellcheck scripts/bootstrap_mail.sh
``` ```
Useful execution commands: Useful execution commands:
```bash ```bash
ansible-playbook ansible/site.yml ansible-playbook ansible/site.yml
ansible-playbook ansible/site.yml --limit ikaros
ansible-playbook ansible/site.yml --limit nymph
ansible-playbook ansible/site.yml --limit deadalus ansible-playbook ansible/site.yml --limit deadalus
scripts/bootstrap_mail.sh scripts/bootstrap_mail.sh
``` ```
## Single-Test Equivalents ## Single-Test Equivalents
There is no pytest, Molecule, or unit-test suite. Use the narrowest command matching the changed area. There is no pytest, Molecule, or unit-test suite. Use the narrowest command matching the changed area.
- Single playbook syntax test: `ansible-playbook ansible/site.yml --syntax-check` - Playbook syntax only: `ansible-playbook ansible/site.yml --syntax-check`
- Single host check: `ansible-playbook ansible/site.yml --limit <host> --check --diff` - Single host dry run: `ansible-playbook ansible/site.yml --limit <host> --check --diff`
- Single task restart point: `ansible-playbook ansible/site.yml --limit <host> --start-at-task "<task name>" --check --diff` - Single task restart point: `ansible-playbook ansible/site.yml --limit <host> --start-at-task "<task name>" --check --diff`
- Single script syntax test: `sh -n scripts/bootstrap_mail.sh` - Single role lint: `ansible-lint ansible/roles/<role>`
- Single script lint: `shellcheck scripts/bootstrap_mail.sh` - Script syntax/lint: `sh -n scripts/bootstrap_mail.sh` and `shellcheck scripts/bootstrap_mail.sh`
When changing one area, prefer: - Prefer one limited-host dry run for vars, templates, dotfiles, packages, services, PAM, display manager, and firewall changes
- vars or inventory: one limited host dry run
- one role: one limited host dry run, plus `ansible-lint ansible/roles/<role>` if available
- one template: one limited host dry run with `--diff`
- one script: `sh -n` and `shellcheck` on that script
## Code Style Guidelines ## Code Style Guidelines
### General ### General
- Keep orchestration in playbooks and implementation in roles - Keep orchestration in playbooks and implementation in roles
@@ -87,42 +87,42 @@ When changing one area, prefer:
- Make state transitions explicit - Make state transitions explicit
- Avoid unrelated refactors in the same change - Avoid unrelated refactors in the same change
- Keep comments sparse and only for non-obvious behavior - Keep comments sparse and only for non-obvious behavior
### YAML And Formatting ### YAML And Formatting
- Start YAML files with `---` - Start YAML files with `---`
- Use 2-space indentation; never use tabs - Use 2-space indentation; never use tabs
- Keep existing ordering stable when editing lists and maps - Keep existing ordering stable when editing lists and maps
- Quote file modes as strings such as `"0644"`, `"0755"`, `"0600"`, `"0700"` - Quote file modes as strings such as `"0644"`, `"0755"`, `"0600"`, `"0700"`
- Avoid formatting-only churn in untouched sections - Avoid formatting-only churn in untouched sections
### Imports, Modules, And Task Structure
- Use FQCN module names such as `ansible.builtin.copy` and `community.general.ufw` ### Modules And Task Structure
- Use FQCN module names such as `ansible.builtin.copy` and `community.general.xbps`
- Prefer dedicated modules over `ansible.builtin.command` or `ansible.builtin.shell` - Prefer dedicated modules over `ansible.builtin.command` or `ansible.builtin.shell`
- Use `command` only when no module fits; use `shell` only for shell features - Use `command` only when no module fits; use `shell` only for shell features
- When using `command` or `shell`, set `changed_when` and `failed_when` when defaults are misleading - When using `command` or `shell`, set `changed_when` and `failed_when` when defaults are misleading
- Keep task names imperative, descriptive, and stable enough for `--start-at-task` - Keep task names imperative, descriptive, and stable enough for `--start-at-task`
- Tag tasks consistently with existing families such as `packages`, `services`, `dotfiles`, `gnome`, and `dotfiles:*` - Tag tasks consistently with existing families such as `packages`, `services`, `dotfiles`, `gnome`, `nvidia`, `emptty`, and `dotfiles:*`
- Prefer `loop` with `loop_control.label` for multi-item tasks - Prefer `loop` with `loop_control.label` for multi-item tasks
- Use handlers for service restarts when configuration changes should trigger them
### Variables, Types, And Naming ### Variables, Types, And Naming
- Use `snake_case` for vars, facts, and registered values - Use `snake_case` for vars, facts, and registered values
- Follow existing families such as `common_packages`, `ubuntu_packages_base`, `profile_packages`, `host_packages`, `workstation_dotfiles`, and `host_enabled_services` - Follow existing families such as `common_packages`, `profile_packages`, `host_packages`, `desktop_dotfiles`, `host_dotfiles`, `enabled_services`, and `host_enabled_services`
- Keep booleans as booleans, not quoted strings - Keep booleans as booleans, not quoted strings
- Keep structured values as YAML lists/maps, not comma-separated strings - Keep structured values as YAML lists/maps, not comma-separated strings
- Guard optional lists with `default([])`, mappings with `default({})`, and strings with `default('')` - Guard optional lists with `default([])`, mappings with `default({})`, and strings with `default('')`
- Build managed-user paths from `{{ user_home }}` - Build managed-user paths from `{{ user_home }}` where applicable
- Put host-specific overrides in `host_vars`, not shared `group_vars` - Put host-specific overrides in `host_vars`, not shared `group_vars`
### Templates And Dotfiles
### Templates, Dotfiles, And Shell
- Keep secrets parameterized through vars; never hardcode them in templates - Keep secrets parameterized through vars; never hardcode them in templates
- Prefer role `templates/` for variable-driven config and role `files/` for static payloads
- Preserve destination paths and permissions unless the task requires a change - Preserve destination paths and permissions unless the task requires a change
- For workstation-only files, prefer `group_vars/workstation.yml` and the workstation role - Dotfiles should stay deployable on real machines; avoid repo-only hacks in `dotfiles/`
- For server-only changes, keep them out of workstation profiles - Prefer POSIX `sh` for simple scripts; use Bash only when needed
- Do not modify Git templates unless the task explicitly concerns Git behavior - Use `set -eu` in POSIX shell scripts unless there is a clear reason not to
### Area-Specific Guidance - Quote variable expansions unless intentional splitting is required
- `ansible/site.yml`: orchestration only; keep it small
- `ansible/inventory/group_vars/*.yml`: shared defaults by scope
- `ansible/inventory/host_vars/*.yml`: host-specific deltas only
- `ansible/roles/*/tasks/main.yml`: implementation details and ordered steps
- `ansible/templates/**/*.j2`: parameterized config files
- `dotfiles/`: deployed user config and session scripts
- `scripts/`: local helper scripts that should remain safe for manual execution
### Error Handling And Safety ### Error Handling And Safety
- Fail early with `ansible.builtin.fail` when prerequisites are missing - Fail early with `ansible.builtin.fail` when prerequisites are missing
- Guard OS-specific, DE-specific, and host-specific behavior with `when` - Guard OS-specific, DE-specific, and host-specific behavior with `when`
@@ -131,30 +131,29 @@ When changing one area, prefer:
- Keep tasks non-interactive unless explicitly user-driven - Keep tasks non-interactive unless explicitly user-driven
- Avoid destructive changes in user homes unless clearly required - Avoid destructive changes in user homes unless clearly required
- For firewall changes, allow required access before enabling the firewall - For firewall changes, allow required access before enabling the firewall
### Shell Script Style - Be careful with display-manager/session changes on desktop hosts; validate on one host first
- Prefer POSIX `sh` for simple scripts; use Bash only when needed
- Use `set -eu` in POSIX shell scripts unless there is a reason not to ## Area-Specific Notes
- Quote variable expansions unless intentional splitting is required - `profile_desktop_i3` now manages `emptty` on Void desktops; keep session changes coordinated with `.xinitrc`
- Use helper functions for repeated checks and cleanup - `dotfiles/desktop/.xinitrc` is part of the X11 session bootstrap path; changes there affect login behavior
- `nymph` has special NVIDIA/PRIME handling; keep host-specific logic guarded by hostname or host vars
- `ikaros` is treated as the more stable personal desktop; prefer validating risky desktop changes elsewhere first
## Validation Expectations Before Finishing ## Validation Expectations Before Finishing
Run the narrowest useful checks for the files you changed.
Default minimum: Default minimum:
```bash ```bash
ansible-playbook ansible/site.yml --syntax-check ansible-playbook ansible/site.yml --syntax-check
``` ```
Preferred for vars, templates, roles, packages, services, PAM, GNOME, mail, firewall, or dotfile changes:
```bash
ansible-playbook ansible/site.yml --limit <host> --check --diff
```
If you touched `scripts/bootstrap_mail.sh`, also run: If you touched `scripts/bootstrap_mail.sh`, also run:
```bash ```bash
sh -n scripts/bootstrap_mail.sh sh -n scripts/bootstrap_mail.sh
shellcheck scripts/bootstrap_mail.sh shellcheck scripts/bootstrap_mail.sh
``` ```
## Agent Workflow Expectations ## Agent Workflow Expectations
- Read the relevant inventory, vars, role tasks, templates, and dotfiles before editing - Read the relevant inventory, vars, role tasks, templates, files, handlers, and dotfiles before editing
- Do not revert unrelated worktree changes made by the user - Do not revert unrelated worktree changes made by the user
- Keep `README.md` and `AGENTS.md` aligned when workflows materially change - Keep `README.md` and `AGENTS.md` aligned when workflows materially change
- If you add a new operational area, also add the validation command agents should run - If you add a new operational area, also add the validation command agents should run
- Prefer host-limited validation first, especially `deadalus` for workstation work and `prometheus` for server work - Prefer host-limited validation first, especially `ikaros` or `nymph` for Void desktop work, `deadalus` for Ubuntu workstation work, and `prometheus` for server work
- Call out checks you could not run and any follow-up verification needed - Call out checks you could not run and any follow-up verification needed