docs: align runbooks and validation structure
This commit is contained in:
Executable
+5
@@ -0,0 +1,5 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
set -euo pipefail
|
||||||
|
repo_root="$(git rev-parse --show-toplevel)"
|
||||||
|
cd "$repo_root"
|
||||||
|
exec scripts/validate-repo.sh
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
repos:
|
||||||
|
- repo: local
|
||||||
|
hooks:
|
||||||
|
- id: validate-repo
|
||||||
|
name: validate repository
|
||||||
|
entry: scripts/validate-repo.sh
|
||||||
|
language: system
|
||||||
|
pass_filenames: false
|
||||||
@@ -2,8 +2,6 @@
|
|||||||
|
|
||||||
This repo is the **agent ops handbook + fact source** for maintaining personal VPS hosts. Prefer verifying live state over assuming docs are complete.
|
This repo is the **agent ops handbook + fact source** for maintaining personal VPS hosts. Prefer verifying live state over assuming docs are complete.
|
||||||
|
|
||||||
Also readable as `agent.md` (symlink → this file).
|
|
||||||
|
|
||||||
## How to work
|
## How to work
|
||||||
|
|
||||||
1. Read [`inventory/hosts.md`](inventory/hosts.md) for the machine list.
|
1. Read [`inventory/hosts.md`](inventory/hosts.md) for the machine list.
|
||||||
@@ -125,7 +123,8 @@ Default triage labels: needs-triage, needs-info, ready-for-agent, ready-for-huma
|
|||||||
|
|
||||||
### Domain docs
|
### Domain docs
|
||||||
|
|
||||||
Single-context layout: `CONTEXT.md` + `docs/adr/` at the repo root. See `docs/agents/domain.md`.
|
Domain-documentation conventions, including lazily created `CONTEXT.md` and
|
||||||
|
`docs/adr/` entries when needed, are described in [`docs/agents/domain.md`](docs/agents/domain.md).
|
||||||
|
|
||||||
## Safety
|
## Safety
|
||||||
|
|
||||||
@@ -158,7 +157,7 @@ Bills, rough notes, and personal clutter stay in the Obsidian vault. This repo h
|
|||||||
## Layout
|
## Layout
|
||||||
|
|
||||||
```
|
```
|
||||||
AGENTS.md / agent.md # this entry (agent.md → AGENTS.md)
|
AGENTS.md # this entry
|
||||||
RUNBOOKS.md # runbook spec (six-field model, naming, review rules)
|
RUNBOOKS.md # runbook spec (six-field model, naming, review rules)
|
||||||
inventory/hosts.md # machine index (human-readable source of truth)
|
inventory/hosts.md # machine index (human-readable source of truth)
|
||||||
ansible/ # playbooks, roles, sanitized control-plane inventory
|
ansible/ # playbooks, roles, sanitized control-plane inventory
|
||||||
|
|||||||
+3
-2
@@ -45,7 +45,8 @@ runbooks/
|
|||||||
## 章节约定
|
## 章节约定
|
||||||
|
|
||||||
- 每份 runbook 顶部含 `## Purpose`(1–2 行)与 `## Scope`(适用/不适用情形)。
|
- 每份 runbook 顶部含 `## Purpose`(1–2 行)与 `## Scope`(适用/不适用情形)。
|
||||||
- 变更型 runbook 额外含 `## Approval gates` 表;破坏性/不可逆操作必须获得明确批准。
|
- 变更型 runbook 必须记录明确的审批门:门控命令式使用 `## Approval gates` 表;
|
||||||
|
流程式在步骤中记录审批动作、证据位置和未批准时的 `STOP`。破坏性/不可逆操作必须获得明确批准。
|
||||||
- 语言约定:**runbook 正文统一使用英文**(由 agent 逐字执行,降低二义性);
|
- 语言约定:**runbook 正文统一使用英文**(由 agent 逐字执行,降低二义性);
|
||||||
元规范文件(AGENTS.md / RUNBOOKS.md / 模板注释)可保留中文。
|
元规范文件(AGENTS.md / RUNBOOKS.md / 模板注释)可保留中文。
|
||||||
- 变更型 runbook 的两种形态:
|
- 变更型 runbook 的两种形态:
|
||||||
@@ -55,7 +56,7 @@ runbooks/
|
|||||||
- **门控命令式(gated command reference)**:已稳定、低歧义、可验证的
|
- **门控命令式(gated command reference)**:已稳定、低歧义、可验证的
|
||||||
操作以命令集 + 门控呈现(现有:`mailcow-update.md`、
|
操作以命令集 + 门控呈现(现有:`mailcow-update.md`、
|
||||||
`ansible-operations.md`、`home-assistant-maintenance.md`、
|
`ansible-operations.md`、`home-assistant-maintenance.md`、
|
||||||
`vaultwarden-sqlite-to-postgres.md`),必须含 Approval gates 或确认变量
|
`matrix-e2ee-update.md`、`vaultwarden-sqlite-to-postgres.md`),必须含 Approval gates 或确认变量
|
||||||
要求 + 显式 STOP,不替代流程式形态。新写的变更 runbook 默认用流程式。
|
要求 + 显式 STOP,不替代流程式形态。新写的变更 runbook 默认用流程式。
|
||||||
- 统一在 `## Safety` 或正文中复用以下通用安全规则(更严格要求优先)。
|
- 统一在 `## Safety` 或正文中复用以下通用安全规则(更严格要求优先)。
|
||||||
|
|
||||||
|
|||||||
+1
-1
@@ -31,7 +31,7 @@ the software deployed there, see [the LAN overview](../docs/lan-overview.md).
|
|||||||
| **dns.windy.lan** | AdGuard Home LAN DNS + Mihomo explicit proxy (PVE VM 120) | `ssh -4 windy@192.168.66.36` | `192.168.66.36` | ✓ (dns_windy_lan) | **active** | [hosts/dns.windy.lan.md](../hosts/dns.windy.lan.md) |
|
| **dns.windy.lan** | AdGuard Home LAN DNS + Mihomo explicit proxy (PVE VM 120) | `ssh -4 windy@192.168.66.36` | `192.168.66.36` | ✓ (dns_windy_lan) | **active** | [hosts/dns.windy.lan.md](../hosts/dns.windy.lan.md) |
|
||||||
| **gw** | EdgeRouter X primary LAN gateway | `ssh -4 zhiqiang@192.168.66.254` | `192.168.66.254` | — (EdgeOS, no ansible) | **active** | [hosts/gw.md](../hosts/gw.md) |
|
| **gw** | EdgeRouter X primary LAN gateway | `ssh -4 zhiqiang@192.168.66.254` | `192.168.66.254` | — (EdgeOS, no ansible) | **active** | [hosts/gw.md](../hosts/gw.md) |
|
||||||
| **ubnt** | UniFi Network Controller (PVE VM 160) | `ssh -4 windy@192.168.66.46` | `192.168.66.46` | ✓ (ubnt) | **active** | [hosts/ubnt.md](../hosts/ubnt.md) |
|
| **ubnt** | UniFi Network Controller (PVE VM 160) | `ssh -4 windy@192.168.66.46` | `192.168.66.46` | ✓ (ubnt) | **active** | [hosts/ubnt.md](../hosts/ubnt.md) |
|
||||||
| **hass.windy.lan** | Home Assistant (HAOS, x88 Pro physical box, LAN55) | `ssh hassio@hass.windy.lan` | `192.168.55.11` | — (HAOS, no ansible) | **active** | [hosts/hass.windy.lan.md](../hosts/hass.windy.lan.md) | (docs: correct hass hardware to x88 Pro physical box; sync CSG v1.3.2)
|
| **hass.windy.lan** | Home Assistant (HAOS, x88 Pro physical box, LAN55) | `ssh hassio@hass.windy.lan` | `192.168.55.11` | — (HAOS, no ansible) | **active** | [hosts/hass.windy.lan.md](../hosts/hass.windy.lan.md) |
|
||||||
|
|
||||||
`status: stub` = known to exist; fill `hosts/<name>.md` when next touched.
|
`status: stub` = known to exist; fill `hosts/<name>.md` when next touched.
|
||||||
|
|
||||||
|
|||||||
@@ -19,6 +19,7 @@ runbooks start from [`_template.md`](_template.md).
|
|||||||
| AdGuard Home health check | [adguard-home-health.md](adguard-home-health.md) | read-only |
|
| AdGuard Home health check | [adguard-home-health.md](adguard-home-health.md) | read-only |
|
||||||
| Matter packet capture | [matter-packet-capture.md](matter-packet-capture.md) | read-only |
|
| Matter packet capture | [matter-packet-capture.md](matter-packet-capture.md) | read-only |
|
||||||
| Home Assistant maintenance | [home-assistant-maintenance.md](home-assistant-maintenance.md) | change (gated) |
|
| Home Assistant maintenance | [home-assistant-maintenance.md](home-assistant-maintenance.md) | change (gated) |
|
||||||
|
| matrix_e2ee integration update | [matrix-e2ee-update.md](matrix-e2ee-update.md) | change (gated) |
|
||||||
| Routine Ansible operations | [ansible-operations.md](ansible-operations.md) | change (allowlisted) |
|
| Routine Ansible operations | [ansible-operations.md](ansible-operations.md) | change (allowlisted) |
|
||||||
| Linear issue → mergeable change | [issue-to-merge.md](issue-to-merge.md) | delivery |
|
| Linear issue → mergeable change | [issue-to-merge.md](issue-to-merge.md) | delivery |
|
||||||
| Failing health/playbook run | [fix-ci.md](fix-ci.md) | change |
|
| Failing health/playbook run | [fix-ci.md](fix-ci.md) | change |
|
||||||
|
|||||||
@@ -56,8 +56,8 @@ scan, inventory cross-check, markdown link check, runbook-spec check, and
|
|||||||
Ansible `--syntax-check`); for changes that alter playbook behavior, also run
|
Ansible `--syntax-check`); for changes that alter playbook behavior, also run
|
||||||
a read-only `ansible-playbook --check` where possible.
|
a read-only `ansible-playbook --check` where possible.
|
||||||
|
|
||||||
**Verification** — `scripts/validate-repo.sh` exits 0; see `RUNBOOKS.md`
|
**Verification** — `scripts/validate-repo.sh` exits 0; the concrete checks
|
||||||
§校验; the concrete checks must match the change type.
|
must match the change type.
|
||||||
|
|
||||||
**Decision** — verification passed → Step 4; failed → Troubleshooting A.
|
**Decision** — verification passed → Step 4; failed → Troubleshooting A.
|
||||||
|
|
||||||
|
|||||||
@@ -1,32 +1,35 @@
|
|||||||
# matrix_e2ee update (hass.windy.lan)
|
# matrix_e2ee update (hass.windy.lan)
|
||||||
|
|
||||||
Update the custom **`matrix_e2ee`** integration on `hass.windy.lan`.
|
## Purpose
|
||||||
|
|
||||||
- Last reviewed: 2026-08-18
|
Update the custom **`matrix_e2ee`** integration on `hass.windy.lan` while
|
||||||
|
preserving a verified rollback point and confirming that Home Assistant loads it.
|
||||||
|
|
||||||
|
## Scope
|
||||||
|
|
||||||
|
- Applicable: deploying a reviewed `matrix_e2ee` source revision to
|
||||||
|
`hass.windy.lan`.
|
||||||
|
- Not applicable: Home Assistant Core upgrades, integration configuration
|
||||||
|
changes, or recovery without a usable live-tree backup.
|
||||||
|
|
||||||
|
## Ownership
|
||||||
|
|
||||||
|
- Owner: personal ops (Windy)
|
||||||
|
- Last reviewed: 2026-08-23
|
||||||
- Related systems: hass.windy.lan (HAOS, `machine: green`)
|
- Related systems: hass.windy.lan (HAOS, `machine: green`)
|
||||||
|
|
||||||
Facts: [hosts/hass.windy.lan.md](../hosts/hass.windy.lan.md) (see § `matrix_e2ee` live tree)
|
## Approval gates
|
||||||
Source: `/home/windy/project/ha-matrix-e2ee` (development clone on workstation)
|
|
||||||
Access: `ssh -o BatchMode=yes hassio@hass.windy.lan 'sudo -n -i <cmd>'`
|
|
||||||
|
|
||||||
> **STOP conditions:** live state conflicts with the prerequisites below (e.g.
|
| Action | Risk | Explicit approval |
|
||||||
> the source repo is not on the target state, the host manifest does not match
|
|---|---|---|
|
||||||
> the source after rsync, or Core fails to start after restart) — stop and
|
| Replace the live integration tree and restart Home Assistant Core | Medium | Yes — user confirmation required |
|
||||||
> record evidence; never bypass a failed check. Roll back per the Rollback
|
|
||||||
> section when Core does not come back up.
|
|
||||||
|
|
||||||
> **SSH config gotcha (verified 2026-08-18):** on the WSL client the systemwide
|
## Safety
|
||||||
> `/etc/ssh/ssh_config.d/20-systemd-ssh-proxy.conf` can be owned by `nobody`
|
|
||||||
> (e.g. under the agent sandbox), making plain `ssh` fail with
|
|
||||||
> `Bad owner or permissions on /etc/ssh/ssh_config.d/20-systemd-ssh-proxy.conf`.
|
|
||||||
> Workaround: add `-F /dev/null` to every ssh/rsync command below (still uses
|
|
||||||
> the default key and `~/.ssh/known_hosts`). If your plain `ssh hassio@...`
|
|
||||||
> works, you can drop it.
|
|
||||||
|
|
||||||
> Domain is **`matrix_e2ee`** (double-e). Older notes may say `matrix_e2e`;
|
- Do not replace the live tree or restart Core without explicit user confirmation.
|
||||||
> paths, events, and services all use `matrix_e2ee`.
|
- If any precondition or verification fails, `STOP` and record evidence before continuing.
|
||||||
|
|
||||||
## Prerequisites
|
## Preconditions
|
||||||
|
|
||||||
- The source repo at `/home/windy/project/ha-matrix-e2ee` is on the **target
|
- The source repo at `/home/windy/project/ha-matrix-e2ee` is on the **target
|
||||||
state**: either a release tag (`git tag -l 'v*'`) or a commit whose
|
state**: either a release tag (`git tag -l 'v*'`) or a commit whose
|
||||||
@@ -41,8 +44,11 @@ Access: `ssh -o BatchMode=yes hassio@hass.windy.lan 'sudo -n -i <cmd>'`
|
|||||||
- The remote host is reachable and `sudo -n -i ha core info` succeeds.
|
- The remote host is reachable and `sudo -n -i ha core info` succeeds.
|
||||||
- The workstation HTTP proxy does not interfere — LAN hosts must be reachable
|
- The workstation HTTP proxy does not interfere — LAN hosts must be reachable
|
||||||
without proxying (unset `http_proxy` / `HTTP_PROXY` if needed).
|
without proxying (unset `http_proxy` / `HTTP_PROXY` if needed).
|
||||||
|
- If the agent sandbox hits `Bad owner or permissions on /etc/ssh/ssh_config.d/20-systemd-ssh-proxy.conf`, add `-F /dev/null` to the `ssh` / `rsync` commands below.
|
||||||
|
- Domain is **`matrix_e2ee`** (double-e). Older notes may say `matrix_e2e`;
|
||||||
|
paths, events, and services all use `matrix_e2ee`.
|
||||||
|
|
||||||
## Update procedure
|
## Procedure
|
||||||
|
|
||||||
### 1. Backup the live tree
|
### 1. Backup the live tree
|
||||||
|
|
||||||
|
|||||||
@@ -134,12 +134,27 @@ fi
|
|||||||
# ---------------------------------------------------------------------------
|
# ---------------------------------------------------------------------------
|
||||||
say "== 4. Runbook spec compliance (RUNBOOKS.md) =="
|
say "== 4. Runbook spec compliance (RUNBOOKS.md) =="
|
||||||
PROCEDURE_RUNBOOKS="fix-ci.md issue-to-merge.md network-change.md network-recovery.md release.md rollback.md"
|
PROCEDURE_RUNBOOKS="fix-ci.md issue-to-merge.md network-change.md network-recovery.md release.md rollback.md"
|
||||||
GATED_REF_RUNBOOKS="mailcow-update.md ansible-operations.md home-assistant-maintenance.md vaultwarden-sqlite-to-postgres.md"
|
GATED_REF_RUNBOOKS="mailcow-update.md ansible-operations.md home-assistant-maintenance.md matrix-e2ee-update.md vaultwarden-sqlite-to-postgres.md"
|
||||||
|
RUNBOOK_INDEX="runbooks/README.md"
|
||||||
for f in runbooks/*.md; do
|
for f in runbooks/*.md; do
|
||||||
base="$(basename "$f")"
|
base="$(basename "$f")"
|
||||||
[ "$base" = "README.md" ] && continue
|
case "$base" in
|
||||||
|
README.md|_template.md) continue ;;
|
||||||
|
esac
|
||||||
if ! grep -q "Last reviewed" "$f"; then fail "$f: missing 'Last reviewed'"; fi
|
if ! grep -q "Last reviewed" "$f"; then fail "$f: missing 'Last reviewed'"; fi
|
||||||
if ! grep -qE "STOP" "$f"; then fail "$f: missing explicit STOP condition"; fi
|
if ! grep -qE "STOP" "$f"; then fail "$f: missing explicit STOP condition"; fi
|
||||||
|
if ! grep -qE '^## Purpose$' "$f"; then fail "$f: missing '## Purpose'"; fi
|
||||||
|
if ! grep -qE '^## Scope$' "$f"; then fail "$f: missing '## Scope'"; fi
|
||||||
|
index_matches="$(grep -cF "]($base)" "$RUNBOOK_INDEX" || true)"
|
||||||
|
if [ "$index_matches" -ne 1 ]; then
|
||||||
|
fail "$f: expected exactly one entry in $RUNBOOK_INDEX (found $index_matches)"
|
||||||
|
fi
|
||||||
|
if grep -F "]($base)" "$RUNBOOK_INDEX" | grep -qF "| change"; then
|
||||||
|
case " $PROCEDURE_RUNBOOKS $GATED_REF_RUNBOOKS " in
|
||||||
|
*" $base "*) ;;
|
||||||
|
*) fail "$f: change runbook is not classified as procedure or gated-command" ;;
|
||||||
|
esac
|
||||||
|
fi
|
||||||
done
|
done
|
||||||
for base in $PROCEDURE_RUNBOOKS; do
|
for base in $PROCEDURE_RUNBOOKS; do
|
||||||
f="runbooks/$base"
|
f="runbooks/$base"
|
||||||
|
|||||||
Reference in New Issue
Block a user