docs: reshape runbooks into .agents/skills/<name>/SKILL.md (phase 4)
Problem: runbooks are agent-executable procedures but lived at the repo root, separate from the other agent instruction now under .agents/. Change: - Move runbooks/<name>.md -> .agents/skills/<name>/SKILL.md (folder per skill, matching the wiki-hq skills layout). Frontmatter (name, risk_class, inputs, verification, docs_update_checklist, transition) preserved. - Rewrite links (inbound from plans; between-skill siblings) via the move map. - Update prose references in AGENTS.md, HERMES.md, .agents/OIKOS.md, and the operations schema; fix a pre-existing stale link to operations/commands.md. No code consumed runbooks/ by path, so nothing else changes. Verification: all SKILL.md frontmatter parses with valid risk_class; every lifecycle transition resolves to an oikos/ontology.yaml state; broken-link count 127 -> 126 (fixed one, introduced none). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -40,7 +40,7 @@ one pass through **Observe → Orient → Decide → Act**:
|
|||||||
|---|---|---|
|
|---|---|---|
|
||||||
| Host / Service | topology entities | `inventory.yaml` (+ generated `hosts/*.yaml`) |
|
| Host / Service | topology entities | `inventory.yaml` (+ generated `hosts/*.yaml`) |
|
||||||
| Secret | SOPS+age encrypted value, per-client recipients | `secrets/` + `.sops.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/<name>/SKILL.md` |
|
||||||
| Signal | something needing attention, with lifecycle | `signals/` ledger (Week 3) |
|
| Signal | something needing attention, with lifecycle | `signals/` ledger (Week 3) |
|
||||||
| Change | one mutation: who, what, risk, approval, verification | `ledger/` (Week 2) |
|
| Change | one mutation: who, what, risk, approval, verification | `ledger/` (Week 2) |
|
||||||
| Approval | short-TTL signed grant for a gated action | approval engine (Week 3) |
|
| Approval | short-TTL signed grant for a gated action | approval engine (Week 3) |
|
||||||
|
|||||||
@@ -20,8 +20,8 @@ versioned, reviewable, and reachable by MCP `get_page`/`search_docs` like any ot
|
|||||||
|
|
||||||
## Runbooks
|
## Runbooks
|
||||||
|
|
||||||
Repeatable procedures live in `runbooks/<name>.md` with YAML front-matter that the Oikos policy and
|
Repeatable procedures are skills — one folder per skill at `.agents/skills/<name>/SKILL.md`, with
|
||||||
lifecycle machinery reads:
|
YAML front-matter that the Oikos policy and lifecycle machinery reads:
|
||||||
|
|
||||||
```yaml
|
```yaml
|
||||||
---
|
---
|
||||||
|
|||||||
@@ -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
|
Goal: bring a new host (workstation, LXC, VM) into inventory and the
|
||||||
secrets model, with mesh membership only where it's actually needed.
|
secrets model, with mesh membership only where it's actually needed.
|
||||||
This wraps the existing `homelab client add` flow — see
|
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.
|
the full walkthrough; this runbook is the risk/lifecycle framing.
|
||||||
|
|
||||||
1. On any enrolled client: `homelab client add <hostname>` — appends a
|
1. On any enrolled client: `homelab client add <hostname>` — appends a
|
||||||
`hosts.<name>:` block to `inventory.yaml` (lifecycle `state: planned`
|
`hosts.<name>:` 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.
|
commits + pushes.
|
||||||
2. Netbird join is **optional, not a required step** — only needed for
|
2. Netbird join is **optional, not a required step** — only needed for
|
||||||
hosts that must be reachable off-LAN (workstations that roam, e.g.
|
hosts that must be reachable off-LAN (workstations that roam, e.g.
|
||||||
@@ -18,10 +18,10 @@ own repo) and get it live, safely.
|
|||||||
`oikos/policy.yaml`.
|
`oikos/policy.yaml`.
|
||||||
2. Clone/pull the `config_repo` (never edit the backend's working tree
|
2. Clone/pull the `config_repo` (never edit the backend's working tree
|
||||||
directly — tracked configs change by commit + push, per
|
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`.
|
3. Make the change, commit, push to `main`.
|
||||||
4. The Gitea webhook fires the deploy pipeline for that repo (see
|
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).
|
the exact receiver/reload for this service).
|
||||||
5. Run the preflight's verification command. If it fails, check
|
5. Run the preflight's verification command. If it fails, check
|
||||||
`homelab service <name> log` for the reload/restart error.
|
`homelab service <name> log` for the reload/restart error.
|
||||||
@@ -9,13 +9,13 @@ transition: "provisioning -> active"
|
|||||||
|
|
||||||
# Lifecycle: activate a node
|
# 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,
|
enrolled if it needs secrets, mesh joined if it needs off-LAN reach,
|
||||||
ingress live if public, health check answering, doc page complete,
|
ingress live if public, health check answering, doc page complete,
|
||||||
ledger entry.
|
ledger entry.
|
||||||
|
|
||||||
1. If the node is a `homelab` client: finish enrollment per
|
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).
|
mesh join, `homelab doctor` green).
|
||||||
2. If it hosts a public service: add the `services:` entry in
|
2. If it hosts a public service: add the `services:` entry in
|
||||||
`inventory.yaml` (backend, url, doc_page, config_repo, risk_notes —
|
`inventory.yaml` (backend, url, doc_page, config_repo, risk_notes —
|
||||||
@@ -9,7 +9,7 @@ transition: "active -> deprecated"
|
|||||||
|
|
||||||
# Lifecycle: deprecate a node
|
# 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
|
but takes no new dependents. **Completion condition: zero remaining
|
||||||
inbound `depends-on`/`routes-to` edges** — this is a hard gate, not a
|
inbound `depends-on`/`routes-to` edges** — this is a hard gate, not a
|
||||||
suggestion; `oikos/policy.yaml` `lifecycle_overrides.deprecated.refuse`
|
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.
|
will catch automatically, but until then this manual check is the gate.
|
||||||
|
|
||||||
Next (once `affected_by` is empty):
|
Next (once `affected_by` is empty):
|
||||||
[lifecycle-destroy-node.md](lifecycle-destroy-node.md).
|
[lifecycle-destroy-node.md](../lifecycle-destroy-node/SKILL.md).
|
||||||
@@ -10,7 +10,7 @@ transition: "active -> migrating -> active"
|
|||||||
# Lifecycle: migrate a node
|
# Lifecycle: migrate a node
|
||||||
|
|
||||||
Modeled on the strong Phase 1+2 migration
|
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;
|
Requires (ontology): preflight + backup-verified before migrating;
|
||||||
post-verify + Caddy backends checked + mounts checked + docs updated
|
post-verify + Caddy backends checked + mounts checked + docs updated
|
||||||
before returning to `active`.
|
before returning to `active`.
|
||||||
@@ -9,7 +9,7 @@ transition: "planned -> provisioning"
|
|||||||
|
|
||||||
# Lifecycle: provision a node
|
# 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 —
|
Policy note: `provisioning` nodes get a lifecycle override —
|
||||||
`config_mutation` actions downgrade to `reversible_low` because nothing
|
`config_mutation` actions downgrade to `reversible_low` because nothing
|
||||||
depends on the node yet (see `oikos/policy.yaml` `lifecycle_overrides`).
|
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.
|
is enough to satisfy the transition requirement.
|
||||||
4. Reserve the IP in DNS/DHCP notes if it's a fixed LAN address.
|
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).
|
||||||
@@ -102,9 +102,9 @@ Then `systemctl status apt-recovery` from a fresh ssh to check progress.
|
|||||||
|
|
||||||
## Related
|
## Related
|
||||||
|
|
||||||
- [Operations cheatsheet](commands.md)
|
- [Operations cheatsheet](../../../operations/commands.md)
|
||||||
- [Auto-deploy pipelines](../knowledge/wiki/infrastructure/auto-deploy.md)
|
- [Auto-deploy pipelines](../../../knowledge/wiki/infrastructure/auto-deploy.md)
|
||||||
- [Hubris host page](../knowledge/wiki/hosts/hubris.md)
|
- [Hubris host page](../../../knowledge/wiki/hosts/hubris.md)
|
||||||
|
|
||||||
## Changelog
|
## Changelog
|
||||||
|
|
||||||
@@ -76,7 +76,8 @@ Grep is fine for browsing or when MCP is unreachable.
|
|||||||
## 4. Wiki conventions
|
## 4. Wiki conventions
|
||||||
|
|
||||||
- Narrative pages live under `knowledge/wiki/{containers,hosts,vms,infrastructure}/`;
|
- Narrative pages live under `knowledge/wiki/{containers,hosts,vms,infrastructure}/`;
|
||||||
procedural pages under `investigations/`, `operations/`, `runbooks/`, `plans/`.
|
runbook procedures under `.agents/skills/<name>/SKILL.md`; other procedural
|
||||||
|
pages under `investigations/`, `operations/`, `plans/`.
|
||||||
Cross-link liberally; orphans are bugs.
|
Cross-link liberally; orphans are bugs.
|
||||||
- Every page ends with a `## Changelog` section, entries in reverse-chrono
|
- Every page ends with a `## Changelog` section, entries in reverse-chrono
|
||||||
order:
|
order:
|
||||||
|
|||||||
@@ -19,8 +19,8 @@ When in doubt, check `/opt/homelab-context/` first.
|
|||||||
|
|
||||||
For the canonical workflows (service health check, config change +
|
For the canonical workflows (service health check, config change +
|
||||||
deploy, client enrollment, incident investigation, and each node
|
deploy, client enrollment, incident investigation, and each node
|
||||||
lifecycle transition), read the matching file in `runbooks/*.md` before
|
lifecycle transition), read the matching `.agents/skills/<name>/SKILL.md` before
|
||||||
acting. Each runbook carries its risk class, required inputs, the
|
acting. Each skill carries its risk class, required inputs, the
|
||||||
verification command, and a docs-update checklist in its frontmatter —
|
verification command, and a docs-update checklist in its frontmatter —
|
||||||
classify against `oikos/policy.yaml` using that risk class before any
|
classify against `oikos/policy.yaml` using that risk class before any
|
||||||
mutation. Don't re-derive topology or the mutation path by grepping the
|
mutation. Don't re-derive topology or the mutation path by grepping the
|
||||||
|
|||||||
@@ -42,7 +42,7 @@ is actually unused end-to-end.
|
|||||||
|
|
||||||
## Provisioning steps (once pve_id is assigned)
|
## 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 <new-id> ...` on hubris — confirm the assigned ID doesn't
|
1. `pct create <new-id> ...` on hubris — confirm the assigned ID doesn't
|
||||||
collide with 131 or anything else live.
|
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,
|
4. Point node_exporter at hubris + strong (either install locally on each,
|
||||||
or scrape via SSH-tunneled metrics — install locally is simpler and is
|
or scrape via SSH-tunneled metrics — install locally is simpler and is
|
||||||
the standard approach).
|
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
|
to flip to `active`, complete the doc page, regenerate
|
||||||
`hosts/*.yaml` + `infrastructure/topology.md`.
|
`hosts/*.yaml` + `infrastructure/topology.md`.
|
||||||
6. Extend `oikos/scheduler.py`'s disk/temp probes to query Prometheus
|
6. Extend `oikos/scheduler.py`'s disk/temp probes to query Prometheus
|
||||||
|
|||||||
Reference in New Issue
Block a user