Document repo workflow for agents

This commit is contained in:
Fabio Scotto di Santolo
2026-03-27 14:33:03 +01:00
parent 5112d0d73d
commit bbe5bb8bdb
2 changed files with 127 additions and 125 deletions

249
AGENTS.md
View File

@@ -1,56 +1,60 @@
# AGENTS.md # AGENTS.md
Guidance for agentic coding tools working in this repository. Guidance for coding agents working in this repository.
Project type: Ansible-based infrastructure and user dotfiles. Project type: Ansible-driven infrastructure, workstation/server provisioning, and user dotfiles.
## Repository Map
## Repository snapshot
- 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` - Shared vars: `ansible/inventory/group_vars/*.yml`
- Host vars: `ansible/inventory/host_vars/*.yml` - Host overrides: `ansible/inventory/host_vars/*.yml`
- Roles: `ansible/roles/*`
- Templates: `ansible/templates/**/*.j2` - Templates: `ansible/templates/**/*.j2`
- Dotfiles source of truth: `dotfiles/` - Dotfiles: `dotfiles/`
- Utility scripts: `scripts/` - Scripts: `scripts/`
- Sensitive material/examples: `secrets/` - Local secrets area: `secrets/`
## Active Topology
## Active orchestration - Void desktops: `ikaros`, `nymph`
- Ubuntu workstation: `deadalus`
- Ubuntu server: `prometheus`
- Most hosts currently use `ansible_connection: local`
## Active Orchestration
`ansible/site.yml` currently applies: `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`
Active roles:
- `dotfiles_common`, `packages_void`, `services_runit`, `profile_desktop_i3`, `packages_ubuntu`, `services_systemd`, `profile_workstation_gnome`, `profile_server`
Roles present but not wired into `ansible/site.yml`: Roles present but not wired into `ansible/site.yml`:
- `base` - `base`
- `dotfiles` - `dotfiles`
## Local Instruction Files
## Local instruction files Checked when this file was updated:
Checked in this repository when this file was written:
- `.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 of these appear later, treat them as higher-priority local instructions. If any appear later, treat them as higher-priority repo-local instructions.
## Working Principles
## Working assumptions - Preserve the layering: `all -> OS -> profile -> host`
- Favor idempotent, host-safe changes over cleverness. - Prefer minimal, targeted edits over cleanup refactors
- Preserve the layering: `all -> OS -> profile -> host`. - Preserve idempotency and reproducibility
- Validate on one host before broad rollout. - Validate on one limited host before broad rollout
- Prefer minimal, targeted edits over cleanup refactors. - Treat `secrets/` as sensitive and never print secret values
- Treat `secrets/` as sensitive and avoid exposing values. - Avoid editing vendored code under `dotfiles/common/.tmux/plugins/` unless explicitly asked
- `dotfiles/common/.tmux/plugins/` contains vendored upstream code. ## Build, Lint, And Test Commands
There is no compile/build pipeline. Confidence comes from syntax checks, dry runs, linting, and targeted script validation.
## Build, lint, and test commands
There is no compile/build step. Validation is based on syntax checks, inventory inspection, dry-runs, and linting.
Install tooling if needed: Install tooling if needed:
```bash ```bash
python3 -m pip install ansible python3 -m pip install ansible ansible-lint yamllint
ansible-galaxy collection install community.general ansible-galaxy collection install community.general
``` ```
Core validation:
Linting and static checks if available locally: ```bash
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 nymph --check --diff
```
Linting and script checks:
```bash ```bash
ansible-lint ansible/site.yml ansible-lint ansible/site.yml
ansible-lint ansible/roles ansible-lint ansible/roles
@@ -58,104 +62,99 @@ yamllint ansible/
sh -n scripts/bootstrap_mail.sh sh -n scripts/bootstrap_mail.sh
shellcheck scripts/bootstrap_mail.sh shellcheck scripts/bootstrap_mail.sh
``` ```
Useful execution commands:
## Single-test equivalents
There is no Molecule, pytest, or dedicated unit-test suite. Use the narrowest validation that matches the change.
Fastest confidence check:
```bash ```bash
ansible-playbook ansible/site.yml --syntax-check ansible-playbook ansible/site.yml
ansible-playbook ansible/site.yml --limit deadalus
scripts/bootstrap_mail.sh
``` ```
## Single-Test Equivalents
Best default dry-runs: There is no pytest, Molecule, or unit-test suite. Use the narrowest command matching the changed area.
```bash - Single playbook syntax test: `ansible-playbook ansible/site.yml --syntax-check`
ansible-playbook ansible/site.yml --limit ikaros --check --diff - Single host check: `ansible-playbook ansible/site.yml --limit <host> --check --diff`
ansible-playbook ansible/site.yml --limit deadalus --check --diff - Single task restart point: `ansible-playbook ansible/site.yml --limit <host> --start-at-task "<task name>" --check --diff`
ansible-playbook ansible/site.yml --limit prometheus --check --diff - Single script syntax test: `sh -n scripts/bootstrap_mail.sh`
``` - Single script lint: `shellcheck scripts/bootstrap_mail.sh`
When changing one area, prefer:
Testing notes: - vars or inventory: one limited host dry run
- Prefer `--limit` aggressively to avoid accidental multi-host rollout. - one role: one limited host dry run, plus `ansible-lint ansible/roles/<role>` if available
- Prefer `--check --diff` before package, service, PAM, bootloader, firewall, or session changes. - one template: one limited host dry run with `--diff`
- Keep task names stable and unique enough for `--start-at-task`. - one script: `sh -n` and `shellcheck` on that script
- If you change only vars, inventory inspection may be the quickest useful check. ## Code Style Guidelines
### General
## Code style guidelines - Keep orchestration in playbooks and implementation in roles
### General principles - Prefer declarative modules over imperative shell commands
- Keep orchestration in playbooks and implementation details in roles. - Make state transitions explicit
- Prefer declarative modules over imperative commands. - Avoid unrelated refactors in the same change
- Avoid unrelated refactors while solving a targeted task. - Keep comments sparse and only for non-obvious behavior
- Preserve idempotency and make state transitions explicit. ### YAML And Formatting
- Start YAML files with `---`
### Ansible modules and task structure - Use 2-space indentation; never use tabs
- Use FQCN module names such as `ansible.builtin.copy` and `community.general.ufw`. - Keep existing ordering stable when editing lists and maps
- Prefer purpose-built modules over `ansible.builtin.command` or `ansible.builtin.shell`. - Quote file modes as strings such as `"0644"`, `"0755"`, `"0600"`, `"0700"`
- Use `command` only when no good module exists; use `shell` only when shell features are required. - Avoid formatting-only churn in untouched sections
- When using `command` or `shell`, set `changed_when` and `failed_when` when defaults are misleading. ### Imports, Modules, And Task Structure
- Keep task names imperative, outcome-based, and unique enough for `--start-at-task`. - Use FQCN module names such as `ansible.builtin.copy` and `community.general.ufw`
- Tag every task consistently with its execution flow, typically `packages`, `services`, `dotfiles`, `gnome`, `nvidia`, or `dotfiles:*`. - Prefer dedicated modules over `ansible.builtin.command` or `ansible.builtin.shell`
- Prefer `loop` with clear `loop_control.label` for user-facing collections. - 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
### YAML formatting - Keep task names imperative, descriptive, and stable enough for `--start-at-task`
- Start YAML files with `---`. - Tag tasks consistently with existing families such as `packages`, `services`, `dotfiles`, `gnome`, and `dotfiles:*`
- Use 2-space indentation and never tabs. - Prefer `loop` with `loop_control.label` for multi-item tasks
- Keep keys, lists, and maps in stable order. ### Variables, Types, And Naming
- Quote file modes as strings: `"0644"`, `"0755"`, `"0600"`, `"0700"`. - Use `snake_case` for vars, facts, and registered values
- Avoid formatting-only churn in untouched sections. - Follow existing families such as `common_packages`, `ubuntu_packages_base`, `profile_packages`, `host_packages`, `workstation_dotfiles`, and `host_enabled_services`
- Keep booleans as booleans, not quoted strings
### Variables, types, and naming - Keep structured values as YAML lists/maps, not comma-separated strings
- Use `snake_case` consistently for variables and facts. - Guard optional lists with `default([])`, mappings with `default({})`, and strings with `default('')`
- Follow existing families such as `common_packages`, `profile_packages`, `host_packages`, `common_dotfiles`, `workstation_dotfiles`, `server_dotfiles`, and `host_dotfiles`. - Build managed-user paths from `{{ user_home }}`
- Keep booleans as booleans, not quoted strings. - Put host-specific overrides in `host_vars`, not shared `group_vars`
- Keep structured data as YAML collections, not comma-separated strings. ### Templates And Dotfiles
- Guard optional collections/maps with `default([])` and `default({})`. - Keep secrets parameterized through vars; never hardcode them in templates
- Guard optional strings with `default('')`. - Preserve destination paths and permissions unless the task requires a change
- Build user paths from `{{ user_home }}` instead of hardcoding home directories. - For workstation-only files, prefer `group_vars/workstation.yml` and the workstation role
- Host-specific overrides belong in `host_vars`, not shared group files. - For server-only changes, keep them out of workstation profiles
- Do not modify Git templates unless the task explicitly concerns Git behavior
### Error handling and safety ### Area-Specific Guidance
- Guard OS-specific or profile-specific behavior with `when` clauses. - `ansible/site.yml`: orchestration only; keep it small
- Prefer explicit inputs over assumptions about host state. - `ansible/inventory/group_vars/*.yml`: shared defaults by scope
- Use `failed_when: false` only for intentional probes or best-effort detection. - `ansible/inventory/host_vars/*.yml`: host-specific deltas only
- Use `no_log: true` for secrets, passwords, and sensitive command results. - `ansible/roles/*/tasks/main.yml`: implementation details and ordered steps
- Keep tasks non-interactive and automation-safe. - `ansible/templates/**/*.j2`: parameterized config files
- Avoid destructive operations in user homes unless clearly required. - `dotfiles/`: deployed user config and session scripts
- Fail early with `ansible.builtin.fail` when prerequisites such as architecture, release metadata, or session bus data are missing. - `scripts/`: local helper scripts that should remain safe for manual execution
- For firewall changes, allow required access before enabling the firewall. ### Error Handling And Safety
- Fail early with `ansible.builtin.fail` when prerequisites are missing
### Shell, scripts, and external code - Guard OS-specific, DE-specific, and host-specific behavior with `when`
- Prefer POSIX `sh` for simple scripts; use Bash only when Bash features are required. - Use `no_log: true` for passwords, tokens, and secret-bearing command results
- Quote variable expansions unless intentional word splitting is required. - Use `failed_when: false` only for intentional probes
- Preserve executable bits for deployed scripts where appropriate. - Keep tasks non-interactive unless explicitly user-driven
- If you add Python later, follow standard-library, third-party, local import grouping. - Avoid destructive changes in user homes unless clearly required
- Treat vendored tmux plugins as upstream code unless the task explicitly targets them. - For firewall changes, allow required access before enabling the firewall
### Shell Script Style
## Editing guidance by area - Prefer POSIX `sh` for simple scripts; use Bash only when needed
- `ansible/site.yml`: keep it small and orchestration-focused. - Use `set -eu` in POSIX shell scripts unless there is a reason not to
- `ansible/inventory/group_vars/*.yml`: shared defaults by layer. - Quote variable expansions unless intentional splitting is required
- `ansible/inventory/host_vars/*.yml`: host-specific overrides only. - Use helper functions for repeated checks and cleanup
- `ansible/roles/*/tasks/main.yml`: role implementation details. ## Validation Expectations Before Finishing
- `ansible/templates/**/*.j2`: keep secrets and host-specific values parameterized. Run the narrowest useful checks for the files you changed.
- `dotfiles/`: user-facing config and session scripts deployed by roles.
- `scripts/`: standalone local utilities; keep them safe to run manually.
## Validation expectations before finishing
Run the narrowest useful checks for the area 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:
Preferred for role, template, or vars changes:
```bash ```bash
ansible-playbook ansible/site.yml --limit <host> --check --diff ansible-playbook ansible/site.yml --limit <host> --check --diff
``` ```
If you touched `scripts/bootstrap_mail.sh`, also run:
## Agent workflow expectations ```bash
- Read the relevant inventory, vars, role tasks, templates, and deployed dotfiles before editing. sh -n scripts/bootstrap_mail.sh
- Do not change unrelated files to "clean things up". shellcheck scripts/bootstrap_mail.sh
- 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. ## Agent Workflow Expectations
- Prefer host-limited validation before broad apply. - Read the relevant inventory, vars, role tasks, templates, and dotfiles before editing
- Call out any verification you could not run. - Do not revert unrelated worktree changes made by the user
- 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
- Prefer host-limited validation first, especially `deadalus` for workstation work and `prometheus` for server work
- Call out checks you could not run and any follow-up verification needed

View File

@@ -10,3 +10,6 @@
- [x] scaricare la posta - [x] scaricare la posta
- [x] init mu per la ricerca - [x] init mu per la ricerca
- [ ] configurare GNOME - [ ] configurare GNOME
- [ ] verificare pacchetti YubiKey/GPG/SSH-FIDO2 sulla workstation Ubuntu
- [ ] configurare YubiKey per GPG signing sulla workstation
- [ ] valutare generazione chiave SSH ed25519-sk sulla workstation