Ctrl K
ComunidadGuías…

AGENTS.md

Rama master · réplica de lectura del repositorio original.

Archivo original ↗Preguntar a KiBot
# AGENTS.md

Concise repository guidance for agentic coding agents. Keep this file short: add detailed runbooks
under `docs/`, and only keep high-signal reminders here.

## Repository Overview

Self-hosted K3s homelab via GitOps. Principles: declarative infra, repeatable automation, small blast radius, version pinning, minimal drift.

**Tech Stack:** K3s, ArgoCD, Helm (template-only), Ansible (bootstrap), External Secrets + Vault, cert-manager, Envoy Gateway (Gateway API), Renovate, ZFS, Cilium (BGP).

**Cluster Access:** This is a GitOps repository. `kubectl --context=grigri`. Metrics: https://prometheus.internal.grigri.cloud

## Repository Map

```
apps/      # Application Helm charts, one release per folder
system/    # Cluster-wide components: ingress, cert-manager, monitoring, identity
platform/  # Supporting operators/services: Vault, external-secrets, git, reloader
bootstrap/ # ArgoCD bootstrap layer
metal/     # Ansible inventory, playbooks, roles for K3s node provisioning
scripts/   # Utility scripts, including deploy-dir.rh for Helm rendering
test/      # Local k3d test helpers
docs/      # MkDocs documentation and runbooks
```

## Build/Lint/Test Commands

```bash
make git-hooks
pre-commit run --all-files
helm dependency build apps/<name>/
helm template --include-crds --namespace <namespace> <release-name> apps/<name>/
helm lint apps/<name>/
```

## Workflows

**Deploying a new application:**
1. Read `docs/conventions/deploying-new-apps.md` — decision trees, patterns, checklist, reference paths (OIDC, Zalando, MinIO)
2. Check existing deployments: `apps/immich/`, `apps/readest/`
3. Run validation commands before committing

## Code Style

- **YAML:** 2-space indent, `---` for multi-doc, yamllint via pre-commit (ignores `templates/`)
- **Helm:** Prefer maintained official/first-party charts; use `app-template` only when none exists. See `docs/conventions/helm.md`
- **Ansible:** `safety` profile. See `docs/conventions/ansible.md`
- **Renovate:** Add hints above image refs — `docs/conventions/helm.md#renovate-integration`
- **Docs:** Troubleshooting in `docs/troubleshooting/`; `AGENTS.md` for links/reminders. See `docs/conventions/documenting-learnings.md`
- **Security:** No hardcoded secrets. ExternalSecret → Vault. Public repo hygiene
- **Personal information:** never commit people's names (household members, children, guests),
  addresses, locations, phone or person details, or which account/token holds which privileges.
  Use roles or rooms instead ("owner", "Office T"). Applies to code, docs, commit messages and PRs
- **Vault CLI:** `export VAULT_ADDR=https://vault.internal.grigri.cloud`; reuses the owner's OIDC login.
  KV v2 mount `secret`: ExternalSecret `remoteRef.key: /<app>/<path>` ↔ `vault kv put secret/<app>/<path>`.
  Never print secret values; load them from a `0600` file and shred it afterwards

## Commit Messages

**Format:** `<scope>: <imperative-description>` — scope is directory or service name. Special scopes: `metal` (Ansible), `docs`, `renovate`.

```
kube-system: Add kata-nvidia coordinator operator
vault: Change to svg logo
monitoring: Update Helm release kube-prometheus-stack to v82.10.1
```

No attribution lines, AI session links or session trailers in commits, PR bodies or comments — the
repos are public (the `no-session-links` commit-msg hook enforces it). Keep GPG signing.

## Deployment Rules

**Commit first, then apply.** Git must contain the change before it is applied anywhere. Never apply
an uncommitted or partially edited tree.

**Owner approval for live changes.** Propose Home Assistant changes made outside git (dashboards,
entity/area registry, integration options) and pushes, then wait for an explicit yes per item.
Analysis and read-only checks need no approval.

### Agents may run

- Read-only inspection: `kubectl get/describe/logs/top`, Prometheus/Grafana/Loki queries,
  `helm template`, `helm lint`, `helm dependency build`, `pre-commit run`
- **Narrowly scoped `metal/` Ansible** for config that is already committed, using explicit
  `--tags` and `--limit`. Example: `cd metal && ANSIBLE_EXTRA_ARGS="-t zfs-config --limit prusik" make prepare`
- **Scoped `k3s` role config apply** for an already-committed, **config-only** change:
  `cd metal && ANSIBLE_EXTRA_ARGS="-t k3s --limit <node>" make cluster`. Re-templates
  `/etc/rancher/k3s/config.yaml` and `k3s.service`, restarts k3s if config changed (idempotent —
  binary install gated on `/usr/local/bin/k3s` absent). Causes ~30–75s API downtime on `prusik`.
  Requires: committed, config-only (no `k3s_version` bump), explicit `--limit`
- ArgoCD sync of an already-committed and pushed change

Report the command and outcome. Prefer narrowest tag/limit. Target by playbook: `prepare.yml`
roles (`prepare`, `setup` incl. `zfs-config`, `swap`, `nvidia-container-runtime`) → `make prepare`;
`cluster.yml` roles (`ntp`, `gvisor`, `k3s`) → `make cluster`. Always `-t <tag> --limit <node>`.

### Never run

- **`kubectl apply/delete/edit/patch`** on cluster resources — ArgoCD `selfHeal: true` with real-time
  watches reverts these almost instantly
- **Node lifecycle / high blast radius:** `make bootstrap`, `make dev`, `make uninstall-k3s`,
  unscoped/all-node `make cluster`, `-t k3s` without `--limit`, k3s version bumps via Ansible
  (changing `k3s_version` or re-downloading binary). These can take down the sole control-plane
  node. Exception: scoped, committed, config-only `-t k3s --limit <node>` — see "Agents may run"
- **Anything data-destroying:** PVC/PV deletion, `zpool destroy`, `zfs destroy`, pool re-creation,
  disk formatting (`prepare_additional_disks_force_format`)
- Untagged or unlimited `make prepare` / `ansible-playbook` runs — always scope them
- `helm install/upgrade` — let ArgoCD do it

When in doubt, or when a change needs a hard prohibition above, stop and hand the user the exact
command.

## Skill Usage

- `debug` skill: live cluster investigation with read-only `kubectl` and Grafana observability only
- Do not copy runbook steps into agent instructions — link to docs instead
- Prefer focused, path-specific docs over broad always-loaded guidance
- Keep durable knowledge in this repo (docs, `AGENTS.md`), not in agent-local memory
- Subagents default to a mid-tier model; use the top model only for genuinely hard tasks, and do not
  spawn agents for work that can be done inline

## Common Pitfalls

Full pitfall index (78 entries grouped by subsystem): `docs/troubleshooting/INDEX.md`

**Pre-deployment rules** (no separate doc — must be known before starting work):

- Forgetting `helm dependency build` after updating `Chart.yaml`
- Missing Renovate hints causes images to not auto-update
- Introducing CRDs without `--include-crds` in helm template
- Not waiting for webhooks (cert-manager, external-secrets) before applying dependent resources
- Forgetting `Prune=false` on PVCs causes data loss on sync
- Comments inside embedded config blocks (strings in `values.yaml` rendered into a ConfigMap, e.g. Alloy, Vector, Loki) are live config: editing them restarts the workload; treat such edits as config changes
- external-dns >= v0.22 reads only `external-dns.kubernetes.io/*`; `external-dns.alpha.kubernetes.io/*` is
  silently ignored (`docs/network/ingress.md#dns-external-dns`)
- Freshly joined node shows `Ready,SchedulingDisabled` for ~1 min: `k3s-agent` system-upgrade Plan
  has `cordon: true`. Don't uncordon by hand — resolves automatically
- Apps with init-container workarounds: log version info, fail loudly (`exit 1`) on mismatch so
  Renovate bumps surface breakage. Check init container logs after version bumps
- ArgoCD `selfHeal: true` reverts `kubectl apply` almost instantly — commit/push first, let ArgoCD
  sync. See `docs/troubleshooting/argocd-gitops-workflow.md`
- Never `kubectl config use-context`/`set-context` (rewrites the owner's kubeconfig default): always
  pass `--context`. The shell is zsh: unquoted variables do not word-split, put multi-step kubectl
  helpers in a bash script

**Subsystem index** (top pitfalls per group — see `docs/troubleshooting/INDEX.md` for full entries):

- **Kubernetes & GitOps** (15): node addition, app-template `tpl` evaluation, topology spread constraints, `eviction-hard` replaces k3s defaults
- **ArgoCD** (6): repo-server probe death-spiral, kustomize OCI auth override, Helm-hook mixing and
  hook-only edits that never converge (`docs/troubleshooting/argocd-helm-hook-provisioning.md`)
- **Monitoring** (9): Grafana sidecar collisions, Vector log loss, Tempo WAL path collision, DiskPressure Loki gaps
- **Networking** (9): Cilium stale BPF datapath, Armbian kernel BPF breakage, nodelocaldns LRP, pfSense alias change keeps old states (`pfsense-alias-change-keeps-old-states.md`), Envoy listener drain (`envoy-gateway-listener-drain.md`), Envoy debugging (`envoy-gateway-debugging.md`)
- **Storage & Backup** (12): prusik RAM-bound latency, ZFS orphan leak, Velero backup chains, CI DinD disk fill
- **Ansible & Infra** (2): cross-host facts in scoped runs, Ubuntu 26.04 compat
- **LLM Infrastructure** (3): Hermes config overwrite, auth failures, persistent CLI tools
- **Desktop & Home** (12): Home Assistant venv/aiohttp/localtuya, localtuya thermostat `hvac_action` needs `heuristic_action`, UI-storage dashboards edited over the websocket API, PVPC negative prices, Shelly CoIoT push, never disable CoIoT on a Gen1 Shelly (breaks HA setup *and* reboot-loops the device when MQTT is on), renaming an HA entity moves its recorder history (use remove-then-promote), Omnibattery `backup_mode` latch (backup threshold 500 W workaround)
- **Applications** (11): Supabase/Zalando bootstrap, GoTrue CORS, Firecrawl nuq schema, Firecrawl
  egress NP probe-timeout rollback (root cause unknown, aggregate denied counters prove nothing)

## Subsystem Docs

- **Cilium:** `docs/conventions/cilium.md` — BGP, TCX, bandwidth limiting
- **Ingress:** `docs/network/ingress.md`: Envoy Gateways, pfSense alias/overrides, DNS, rollback; routes: `docs/conventions/gateway-api-routes.md`
- **Deploying new apps:** `docs/conventions/deploying-new-apps.md` — decision-making, patterns, checklist
- **Kanidm:** `docs/user-guide/kanidm.md` — Kaniop CRDs, OAuth2 clients, group membership rules (person membership manual, never via CRD)
- **Documenting learnings:** `docs/conventions/documenting-learnings.md` — when/how to write troubleshooting docs
- **prusik storage:** `docs/conventions/prusik-fast-storage-tier.md` — ZFS pool sizing, SSD selection, PVC migration. Hardware: `docs/hardware/prusik.md`, `docs/hardware/k8s-amd64-1.md`
- **Adding a node:** `docs/user-guide/add-or-remove-nodes.md` (runbook), `planning/k8s-amd64-1-node-addition.md` (worked example)
- **Topology spread:** `docs/conventions/topology-spread-constraints.md` — `matchLabelKeys`
- **ESPHome devices (flash, logs, rename):** `apps/esphome/config/README.md` ("Agent Runbook"); hardening TODO `planning/esphome-security-hardening-todo.md`
- **Battery optimizer:** app code in `pando85/home-energy-optimizer`; deployment + extraction plan `planning/energy-baseline-production-execution.md`; live control rollout/rollback `docs/deployment/battery-optimizer.md#live-battery-control`

## Licensing

GPLv3 (see LICENSE.md). Generated code must be compatible.