diff --git a/.agents/OIKOS.md b/.agents/OIKOS.md index fe1fa17..af30e59 100644 --- a/.agents/OIKOS.md +++ b/.agents/OIKOS.md @@ -40,7 +40,7 @@ one pass through **Observe → Orient → Decide → Act**: |---|---|---| | Host / Service | topology entities | `inventory.yaml` (+ generated `hosts/*.yaml`) | | Secret | SOPS+age encrypted value, per-client recipients | `secrets/` + `.sops.yaml` | -| Runbook | executable workflow with risk class + verification | `runbooks/` (Week 2) | +| Runbook | executable workflow with risk class + verification | `.agents/skills//SKILL.md` | | Signal | something needing attention, with lifecycle | `signals/` ledger (Week 3) | | Change | one mutation: who, what, risk, approval, verification | `ledger/` (Week 2) | | Approval | short-TTL signed grant for a gated action | approval engine (Week 3) | diff --git a/.agents/domains/operations/schema.md b/.agents/domains/operations/schema.md index ba8ca84..aadef2b 100644 --- a/.agents/domains/operations/schema.md +++ b/.agents/domains/operations/schema.md @@ -20,8 +20,8 @@ versioned, reviewable, and reachable by MCP `get_page`/`search_docs` like any ot ## Runbooks -Repeatable procedures live in `runbooks/.md` with YAML front-matter that the Oikos policy and -lifecycle machinery reads: +Repeatable procedures are skills — one folder per skill at `.agents/skills//SKILL.md`, with +YAML front-matter that the Oikos policy and lifecycle machinery reads: ```yaml --- diff --git a/runbooks/client-enrollment.md b/.agents/skills/client-enrollment/SKILL.md similarity index 92% rename from runbooks/client-enrollment.md rename to .agents/skills/client-enrollment/SKILL.md index 7de5e4a..6939e96 100644 --- a/runbooks/client-enrollment.md +++ b/.agents/skills/client-enrollment/SKILL.md @@ -11,12 +11,12 @@ docs_update_checklist: [hosts_narrative_page_if_lxc_or_vm] Goal: bring a new host (workstation, LXC, VM) into inventory and the secrets model, with mesh membership only where it's actually needed. This wraps the existing `homelab client add` flow — see -[operations/agent-enrollment.md](../operations/agent-enrollment.md) for +[operations/agent-enrollment.md](../../../operations/agent-enrollment.md) for the full walkthrough; this runbook is the risk/lifecycle framing. 1. On any enrolled client: `homelab client add ` — appends a `hosts.:` block to `inventory.yaml` (lifecycle `state: planned` - → `provisioning`, per [oikos/ontology.yaml](../oikos/ontology.yaml)), + → `provisioning`, per [oikos/ontology.yaml](../../../oikos/ontology.yaml)), commits + pushes. 2. Netbird join is **optional, not a required step** — only needed for hosts that must be reachable off-LAN (workstations that roam, e.g. diff --git a/runbooks/config-change-deploy.md b/.agents/skills/config-change-deploy/SKILL.md similarity index 91% rename from runbooks/config-change-deploy.md rename to .agents/skills/config-change-deploy/SKILL.md index e86d8d6..3b4668f 100644 --- a/runbooks/config-change-deploy.md +++ b/.agents/skills/config-change-deploy/SKILL.md @@ -18,10 +18,10 @@ own repo) and get it live, safely. `oikos/policy.yaml`. 2. Clone/pull the `config_repo` (never edit the backend's working tree directly — tracked configs change by commit + push, per - [OIKOS.md](../OIKOS.md) conventions). + [OIKOS.md](../../../OIKOS.md) conventions). 3. Make the change, commit, push to `main`. 4. The Gitea webhook fires the deploy pipeline for that repo (see - [infrastructure/auto-deploy.md](../knowledge/wiki/infrastructure/auto-deploy.md) for + [infrastructure/auto-deploy.md](../../../knowledge/wiki/infrastructure/auto-deploy.md) for the exact receiver/reload for this service). 5. Run the preflight's verification command. If it fails, check `homelab service log` for the reload/restart error. diff --git a/runbooks/incident-investigation.md b/.agents/skills/incident-investigation/SKILL.md similarity index 100% rename from runbooks/incident-investigation.md rename to .agents/skills/incident-investigation/SKILL.md diff --git a/runbooks/lifecycle-activate-node.md b/.agents/skills/lifecycle-activate-node/SKILL.md similarity index 90% rename from runbooks/lifecycle-activate-node.md rename to .agents/skills/lifecycle-activate-node/SKILL.md index dd3772b..bc04a0d 100644 --- a/runbooks/lifecycle-activate-node.md +++ b/.agents/skills/lifecycle-activate-node/SKILL.md @@ -9,13 +9,13 @@ transition: "provisioning -> active" # Lifecycle: activate a node -Per [oikos/ontology.yaml](../oikos/ontology.yaml). Requires: age key +Per [oikos/ontology.yaml](../../../oikos/ontology.yaml). Requires: age key enrolled if it needs secrets, mesh joined if it needs off-LAN reach, ingress live if public, health check answering, doc page complete, ledger entry. 1. If the node is a `homelab` client: finish enrollment per - [client-enrollment.md](client-enrollment.md) (`--finalize-pubkey`, + [client-enrollment.md](../client-enrollment/SKILL.md) (`--finalize-pubkey`, mesh join, `homelab doctor` green). 2. If it hosts a public service: add the `services:` entry in `inventory.yaml` (backend, url, doc_page, config_repo, risk_notes — diff --git a/runbooks/lifecycle-deprecate-node.md b/.agents/skills/lifecycle-deprecate-node/SKILL.md similarity index 91% rename from runbooks/lifecycle-deprecate-node.md rename to .agents/skills/lifecycle-deprecate-node/SKILL.md index b667494..af4c15c 100644 --- a/runbooks/lifecycle-deprecate-node.md +++ b/.agents/skills/lifecycle-deprecate-node/SKILL.md @@ -9,7 +9,7 @@ transition: "active -> deprecated" # Lifecycle: deprecate a node -Per [oikos/ontology.yaml](../oikos/ontology.yaml): a node keeps running +Per [oikos/ontology.yaml](../../../oikos/ontology.yaml): a node keeps running but takes no new dependents. **Completion condition: zero remaining inbound `depends-on`/`routes-to` edges** — this is a hard gate, not a suggestion; `oikos/policy.yaml` `lifecycle_overrides.deprecated.refuse` @@ -32,4 +32,4 @@ before proceeding — that's exactly the kind of drift the Week-3 detector will catch automatically, but until then this manual check is the gate. Next (once `affected_by` is empty): -[lifecycle-destroy-node.md](lifecycle-destroy-node.md). +[lifecycle-destroy-node.md](../lifecycle-destroy-node/SKILL.md). diff --git a/runbooks/lifecycle-destroy-node.md b/.agents/skills/lifecycle-destroy-node/SKILL.md similarity index 100% rename from runbooks/lifecycle-destroy-node.md rename to .agents/skills/lifecycle-destroy-node/SKILL.md diff --git a/runbooks/lifecycle-migrate-node.md b/.agents/skills/lifecycle-migrate-node/SKILL.md similarity index 96% rename from runbooks/lifecycle-migrate-node.md rename to .agents/skills/lifecycle-migrate-node/SKILL.md index da1c82a..e8a6e52 100644 --- a/runbooks/lifecycle-migrate-node.md +++ b/.agents/skills/lifecycle-migrate-node/SKILL.md @@ -10,7 +10,7 @@ transition: "active -> migrating -> active" # Lifecycle: migrate a node Modeled on the strong Phase 1+2 migration -([plans/2026-06-03_110000-library-ssd-migration-to-ludo-mini.md](../plans/2026-06-03_110000-library-ssd-migration-to-ludo-mini.md)). +([plans/2026-06-03_110000-library-ssd-migration-to-ludo-mini.md](../../../plans/2026-06-03_110000-library-ssd-migration-to-ludo-mini.md)). Requires (ontology): preflight + backup-verified before migrating; post-verify + Caddy backends checked + mounts checked + docs updated before returning to `active`. diff --git a/runbooks/lifecycle-provision-node.md b/.agents/skills/lifecycle-provision-node/SKILL.md similarity index 89% rename from runbooks/lifecycle-provision-node.md rename to .agents/skills/lifecycle-provision-node/SKILL.md index 1f0fb6b..d12ecdb 100644 --- a/runbooks/lifecycle-provision-node.md +++ b/.agents/skills/lifecycle-provision-node/SKILL.md @@ -9,7 +9,7 @@ transition: "planned -> provisioning" # Lifecycle: provision a node -Per [oikos/ontology.yaml](../oikos/ontology.yaml) `lifecycle.transitions`. +Per [oikos/ontology.yaml](../../../oikos/ontology.yaml) `lifecycle.transitions`. Policy note: `provisioning` nodes get a lifecycle override — `config_mutation` actions downgrade to `reversible_low` because nothing depends on the node yet (see `oikos/policy.yaml` `lifecycle_overrides`). @@ -30,4 +30,4 @@ chosen, doc page stub. is enough to satisfy the transition requirement. 4. Reserve the IP in DNS/DHCP notes if it's a fixed LAN address. -Next: [lifecycle-activate-node.md](lifecycle-activate-node.md). +Next: [lifecycle-activate-node.md](../lifecycle-activate-node/SKILL.md). diff --git a/runbooks/runbook-budget-from-csv.md b/.agents/skills/runbook-budget-from-csv/SKILL.md similarity index 100% rename from runbooks/runbook-budget-from-csv.md rename to .agents/skills/runbook-budget-from-csv/SKILL.md diff --git a/runbooks/runbook-dpkg-interrupted.md b/.agents/skills/runbook-dpkg-interrupted/SKILL.md similarity index 95% rename from runbooks/runbook-dpkg-interrupted.md rename to .agents/skills/runbook-dpkg-interrupted/SKILL.md index c619142..53ab143 100644 --- a/runbooks/runbook-dpkg-interrupted.md +++ b/.agents/skills/runbook-dpkg-interrupted/SKILL.md @@ -102,9 +102,9 @@ Then `systemctl status apt-recovery` from a fresh ssh to check progress. ## Related -- [Operations cheatsheet](commands.md) -- [Auto-deploy pipelines](../knowledge/wiki/infrastructure/auto-deploy.md) -- [Hubris host page](../knowledge/wiki/hosts/hubris.md) +- [Operations cheatsheet](../../../operations/commands.md) +- [Auto-deploy pipelines](../../../knowledge/wiki/infrastructure/auto-deploy.md) +- [Hubris host page](../../../knowledge/wiki/hosts/hubris.md) ## Changelog diff --git a/runbooks/service-health-check.md b/.agents/skills/service-health-check/SKILL.md similarity index 100% rename from runbooks/service-health-check.md rename to .agents/skills/service-health-check/SKILL.md diff --git a/AGENTS.md b/AGENTS.md index ea72a46..f330689 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -76,7 +76,8 @@ Grep is fine for browsing or when MCP is unreachable. ## 4. Wiki conventions - Narrative pages live under `knowledge/wiki/{containers,hosts,vms,infrastructure}/`; - procedural pages under `investigations/`, `operations/`, `runbooks/`, `plans/`. + runbook procedures under `.agents/skills//SKILL.md`; other procedural + pages under `investigations/`, `operations/`, `plans/`. Cross-link liberally; orphans are bugs. - Every page ends with a `## Changelog` section, entries in reverse-chrono order: diff --git a/HERMES.md b/HERMES.md index 03fe761..927dd18 100644 --- a/HERMES.md +++ b/HERMES.md @@ -19,8 +19,8 @@ When in doubt, check `/opt/homelab-context/` first. For the canonical workflows (service health check, config change + deploy, client enrollment, incident investigation, and each node -lifecycle transition), read the matching file in `runbooks/*.md` before -acting. Each runbook carries its risk class, required inputs, the +lifecycle transition), read the matching `.agents/skills//SKILL.md` before +acting. Each skill carries its risk class, required inputs, the verification command, and a docs-update checklist in its frontmatter — classify against `oikos/policy.yaml` using that risk class before any mutation. Don't re-derive topology or the mutation path by grepping the diff --git a/plans/2026-07-05-oikos-prometheus-lxc.md b/plans/2026-07-05-oikos-prometheus-lxc.md index b474f12..d2922ef 100644 --- a/plans/2026-07-05-oikos-prometheus-lxc.md +++ b/plans/2026-07-05-oikos-prometheus-lxc.md @@ -42,7 +42,7 @@ is actually unused end-to-end. ## Provisioning steps (once pve_id is assigned) -Follow [runbooks/lifecycle-provision-node.md](../runbooks/lifecycle-provision-node.md): +Follow [lifecycle-provision-node](../.agents/skills/lifecycle-provision-node/SKILL.md): 1. `pct create ...` on hubris — confirm the assigned ID doesn't collide with 131 or anything else live. @@ -53,7 +53,7 @@ Follow [runbooks/lifecycle-provision-node.md](../runbooks/lifecycle-provision-no 4. Point node_exporter at hubris + strong (either install locally on each, or scrape via SSH-tunneled metrics — install locally is simpler and is the standard approach). -5. Follow [runbooks/lifecycle-activate-node.md](../runbooks/lifecycle-activate-node.md) +5. Follow [lifecycle-activate-node](../.agents/skills/lifecycle-activate-node/SKILL.md) to flip to `active`, complete the doc page, regenerate `hosts/*.yaml` + `infrastructure/topology.md`. 6. Extend `oikos/scheduler.py`'s disk/temp probes to query Prometheus