docs: close out the instruction arc — t740 corrected on evidence, registers, ledger, S-37
gates / gates (push) Successful in 8s
gates / gates (push) Successful in 8s
target-selection.md said demo-hp has no off-site tier. Measured first: pvesm list felhom-pbs on the box returns two snapshots in demo-hp's OWN namespace (2026-07-28, 2026-08-04) against ep0's felhom-offsite. The claim was TRUE WHEN WRITTEN and went stale when F10 resolved 2026-07-23. The measurement is kept in an HTML comment beside the corrected sentence. This file decides which machine may be destroyed, so the sentence was load-bearing, not cosmetic. R-229(b) CLOSED (agent 175 -> 99 eff). R-230(b) CLOSED (symlink, proven from fresh sessions). R-230(a) part-actioned -- three false statements fixed, WARN loop added, bulk ruling still owed. S-37: a claim in an instruction file is checked, not trusted.
This commit is contained in:
@@ -0,0 +1,218 @@
|
||||
# LEDGER — instruction arc close-out (agent split, memory truth, checks 6-content and 7, symlink, t740, context7)
|
||||
|
||||
Third and final part. Companions: `LEDGER-instruction-trim-2026-08-06.md`,
|
||||
`LEDGER-instruction-trim-part2-2026-08-06.md`. Same per-block format.
|
||||
|
||||
**Baselines, reconfirmed live before editing, all clean and `HEAD == origin/main`:** `felhom.eu`
|
||||
`92a076c239b9`, `felhom-controller` `66d80efb9f20`, `felhom-agent` `5b2666e3a2ae`,
|
||||
`app-catalog-felhom.eu` `459766cb1639`.
|
||||
|
||||
---
|
||||
|
||||
## A. `felhom-agent/CLAUDE.md` — 175 → 99 effective lines
|
||||
|
||||
Measured 175, not the spec's 173: the CI correction pushed in part 2 added two lines.
|
||||
|
||||
| Heading / first words | Class | Destination | Reason |
|
||||
|---|---|---|---|
|
||||
| `## Layout (verified against the tree)` (27 ln) | derivable | `rule-file:*` + `deleted-derivable` | the tree and `REUSE.md` are its home — but the per-package annotations that were doing real work moved into the rule file for the area they describe, rather than being dropped as the controller's were |
|
||||
| `## Build / run` release table + R-115/R-186/R-188 narrative (34 ln) | duplicated | `already-in:` the `felhom-build-deploy` skill | the file already said "never hand-roll it" and then restated the table, which drifts from the script it describes |
|
||||
| UPID/`WaitTask`, privsep intersection, TLS pinning (6 ln) | path-bound | `rule-file:proxmox.md` | only bite when `internal/proxmox/**` is open |
|
||||
| destructive-op trap rows (4 ln, from `REUSE.md` §3) | path-bound | `rule-file:proxmox.md` | |
|
||||
| local-API scoping, nonce store, bind traps | path-bound | `rule-file:localapi.md` | |
|
||||
| PBS three laws, verify default, prune grant | path-bound | `rule-file:backup.md` | |
|
||||
| format-safety, durable-ID schemes, escrow errors | path-bound | `rule-file:storage.md` | |
|
||||
| `## Demo host` addresses (8 ln) | duplicated | `already-in:operations/nodes.md` | replaced by two rows in the retrieval map |
|
||||
| CHANGELOG/REPORT/secrets blockquote, code-quality line | duplicated | `already-in:CLAUDE.md` (workspace root) | |
|
||||
| artifact taxonomy, `TASK.md`/`RUNBOOK-*.md` (12 ln) | duplicated | `already-in:CLAUDE.md` (workspace root) | |
|
||||
|
||||
**Kept in the core** — it is the only part re-injected after `/compact`: the **root-CLI fence and its
|
||||
three named exceptions**, the destructive-op gate, prove-ownership (audit A1), the gate entry point,
|
||||
the F9 live-validation fence, trunk-based with its revert-and-report escape hatch, and the checklist.
|
||||
|
||||
**New:** `.claude/rules/{proxmox,localapi,backup,storage}.md`, all ≤46 effective lines.
|
||||
|
||||
**Glob overlap, stated rather than silently resolved.** `health-checks.md` already matched
|
||||
`internal/{capability,storage,localapi,hub,guesthook}/**`, which `localapi.md` and `storage.md` now
|
||||
also match. Both rules load in those directories and neither supersedes the other; each new file says
|
||||
so in its own text, so a reader who sees two rules fire is not left guessing which wins.
|
||||
|
||||
---
|
||||
|
||||
## B. The memory index — three false statements, corrected
|
||||
|
||||
**Backup first:** `/mnt/5_hdd/felhom.eu/backups/claude-memory-20260806-112853` (158 files).
|
||||
|
||||
**The premise needed correcting before the work could be done, and the error was mine.** Part 2's
|
||||
report said "3 expired temporal statements", and this task inherited that number. Re-run with the
|
||||
cause printed, **all three matched the ISO date inside a markdown link TARGET** — a filename, not a
|
||||
claim — while the one real expired claim in the same file was written `~08-02`, carried no ISO date,
|
||||
and was never matched. A scan that reports the wrong three and misses the right one is worse than no
|
||||
scan.
|
||||
|
||||
The three genuinely false statements, each established by evidence rather than by the scan:
|
||||
|
||||
| Line | Claim | How it was falsified |
|
||||
|---|---|---|
|
||||
| 17 | `R-193 decision open` | its register row reads `**CLOSED 2026-08-05 — controller v0.200.0**` |
|
||||
| 34 | `demo boxes REMOTE till ~08-02` | live: `ssh felhom-pve` answers and holds `192.168.0.162/24` on `vmbr0` — the home LAN, same /24 as DooPlex |
|
||||
| 68 | `OPEN R-25b` | ROADMAP: `**SHIPPED hub v0.69.0 (2026-07-21)**`; capability map: `R-25b CLOSED` |
|
||||
|
||||
Only the temporal claim was removed from line 34; its durable half — that `ssh felhom-pve` still
|
||||
resolves to the **tailnet** address while `felhom-pve-lan` is the LAN alias — was kept, because it is
|
||||
still true and still surprising.
|
||||
|
||||
**Nothing else in the file was edited. No memory file was deleted. 158 files before and after.**
|
||||
The remaining 32 version literals and 4 host addresses stay, for the warning loop to work on — their
|
||||
survival is deliberate, not an oversight.
|
||||
|
||||
---
|
||||
|
||||
## C. Check 6 gains content WARNings; check 7 is new
|
||||
|
||||
### Why WARN and not FAIL for the index
|
||||
Claude writes `MEMORY.md` between sessions, so a hard failure would refuse a human's push over a line
|
||||
no human typed. The warning is read by the same model that will next edit the file, which makes the
|
||||
loop self-correcting rather than a chore for a person.
|
||||
|
||||
### Check 7 — a citation that calls a register item OPEN must be right
|
||||
|
||||
**Deviation from the task's literal wording, stated because it is a real one.** The task says every
|
||||
citation of a non-open item must itself contain `CLOSED`. Applied literally that fires on ~30
|
||||
legitimate provenance citations — `(R-161)`, `R-117 spike §6.3` — which cite an item as the **source
|
||||
of a fact**, not as outstanding work. A gate that noisy is switched off, which is precisely the fate
|
||||
R-29 documented. **The trigger is therefore an OPENNESS CLAIM**, which still convicts both real
|
||||
defects and keeps the spec's required pass case (`R-168, CLOSED 2026-08-02`) green.
|
||||
|
||||
**Two bugs found by this check's own red-proofs, both of which would have shipped:**
|
||||
|
||||
1. **The state marker is not self-closing.** Real rows read `**SHIPPED — and the alarm is
|
||||
DEMONSTRATED**`. The first parser required `**SHIPPED**` and therefore read **R-168 — the row the
|
||||
whole check exists for — as OPEN**. A gate that cannot convict its own founding case is decoration.
|
||||
2. **The CLOSED exemption was line-wide.** `- [Customer RESET shipped](customer-reset-…-2026-07-17.md)
|
||||
— …; OPEN R-25b` contains "shipped" twice, in a title and a filename, and the whole line was
|
||||
pardoned. Found **only because the red-proof failed to go red**, and now scoped to the citation's
|
||||
clause with a regression test.
|
||||
|
||||
**Suite 39 → 68 assertions, 0 failures.** Red-proofs against real files, both directions, quoted in
|
||||
the report.
|
||||
|
||||
**What check 7 finds across the four repos right now: nothing** — 19 citations, 0 failures. That is
|
||||
because part 2 already corrected the four stale sentences; the red-proof, not the zero, is what shows
|
||||
the check works.
|
||||
|
||||
---
|
||||
|
||||
## D. The workspace symlink (R-230(b)) — done, and PROVEN
|
||||
|
||||
`/mnt/5_hdd/felhom.eu/git/CLAUDE.md` is now a **relative symlink** to
|
||||
`felhom.eu/documentation/runbooks/workspace-CLAUDE.md`. Backup of the pre-link file:
|
||||
`/mnt/5_hdd/felhom.eu/backups/workspace-CLAUDE.md.bak-20260806-113952`.
|
||||
|
||||
**Check 5 now has two legal shapes and asserts a different thing in each:**
|
||||
|
||||
| Shape | Asserted | Rationale |
|
||||
|---|---|---|
|
||||
| LINK | it points at the versioned copy **and resolves to a real file** | divergence is impossible; what can still break is the link. **A dangling link is worse than a diverged copy** — the instructions load NOTHING and there is no content left to notice is wrong |
|
||||
| COPY | byte-identical, as before | a clone elsewhere may legitimately have two files; the link is not forced on anyone |
|
||||
|
||||
**Proven, not assumed** — three fresh sessions each logged
|
||||
`session_start … /mnt/5_hdd/felhom.eu/git/CLAUDE.md` (Claude Code reports the LINK path, not the
|
||||
resolved one). And because a logged path proves discovery rather than delivery, a fourth fresh
|
||||
session **with no tools at all** was asked to quote standing rule 1 and returned it verbatim. The
|
||||
content reaches the model.
|
||||
|
||||
---
|
||||
|
||||
## E. The t740 off-site claim — measured, then corrected
|
||||
|
||||
`target-selection.md` said the PBS-DR / off-site tier is carried by the N100 and **"(demo-hp has
|
||||
none)"**, and used that as the reason to steer backup-disturbing tests at demo-felhom.
|
||||
|
||||
**Measured on the box, from the tier's own evidence:**
|
||||
|
||||
```
|
||||
demo-hp:/etc/pve/storage.cfg pbs: felhom-pbs -> datastore felhom-offsite, server 10.77.0.1,
|
||||
namespace demo-hp, username felhom@pbs!demo-hp
|
||||
demo-hp# LC_ALL=C pvesm list felhom-pbs
|
||||
felhom-pbs:backup/ct/9201/2026-07-28T19:19:45Z pbs-ct 6264034048 9201
|
||||
felhom-pbs:backup/ct/9201/2026-08-04T19:24:16Z pbs-ct 4637840512 9201
|
||||
ep0:/mnt/pbs-datastore/ns/ c11 demo-felhom demo-hp rewalk
|
||||
```
|
||||
|
||||
Two snapshots, newest two days old, in demo-hp's **own namespace** on the shared off-site datastore.
|
||||
**The claim is false.** It was **true when written** and went stale when F10 resolved on 2026-07-23 —
|
||||
the first snapshot is 2026-07-28. Corrected, with the measurement kept in an HTML comment beside it.
|
||||
|
||||
**Why this outranked a typo:** the sentence was load-bearing for "which machine may be destroyed".
|
||||
"Its backup chain is not disturbable" is exactly the belief under which a drill lands somewhere it
|
||||
should not.
|
||||
|
||||
---
|
||||
|
||||
## F. context7 — diagnosed, nothing written
|
||||
|
||||
**There is no Node.js on DooPlex at all.** `npx`, `node` and `npm` are all absent from `PATH`, no
|
||||
`nodejs`/`npm` package is installed, and no runtime directory exists. The plugin manifest
|
||||
(`~/.claude/plugins/.../context7/.mcp.json`) is:
|
||||
|
||||
```json
|
||||
{ "context7": { "command": "npx", "args": ["-y", "@upstash/context7-mcp"] } }
|
||||
```
|
||||
|
||||
So the `ENOENT` is literal: the `npx` binary does not exist. The fix is one package install away —
|
||||
**and that decision is not this task's to make.** DooPlex is Tier 2 and *is* the recovery chain
|
||||
(hub, Gitea, registry, PBS, k3s+Longhorn); adding a language runtime to it for a docs-lookup server
|
||||
is its own change with its own review, not a rider on a documentation task.
|
||||
|
||||
**Whether it is worth pursuing — measured, not repeated from the spec:**
|
||||
|
||||
| Module | Direct third-party dependencies |
|
||||
|---|---|
|
||||
| `felhom-agent` | **1** (`golang.org/x/crypto`) |
|
||||
| `felhom.eu/hub` | **3** |
|
||||
| `felhom-controller` | **6** |
|
||||
|
||||
~8 distinct packages, all small, stable and well known. The plausible consumer is the app catalog's
|
||||
upstream images — and there the skill's existing trap already answers it: **a more
|
||||
authoritative-sounding source of guesses is still a source of guesses, and `docker inspect` decides.**
|
||||
Per §6, **nothing was written** to `felhom-app-catalog/SKILL.md` or to any rule file.
|
||||
|
||||
---
|
||||
|
||||
## G. Before / after
|
||||
|
||||
| File | before (eff/B) | after (eff/B) |
|
||||
|---|---|---|
|
||||
| workspace root `CLAUDE.md` | 142 / 11,280 | **142 / 11,280 — now a SYMLINK, one file not two** |
|
||||
| `felhom.eu/CLAUDE.md` | 117 / 8,006 | 117 / 8,006 (untouched) |
|
||||
| `felhom-controller/CLAUDE.md` | 92 / 6,341 | 92 / 6,341 (untouched) |
|
||||
| **`felhom-agent/CLAUDE.md`** | **175 / 14,093** | **99 / 6,267** |
|
||||
| `app-catalog-felhom.eu/CLAUDE.md` | 80 / 6,397 | 80 / 6,397 (untouched) |
|
||||
| rule files, workspace-wide | 9 | **13**, every one `paths:`-scoped, all ≤60 effective |
|
||||
| `MEMORY.md` | 150 ln / 17,977 B | 150 ln / 18,078 B — 3 statements corrected |
|
||||
| gate suite | 39 assertions | **68** |
|
||||
|
||||
Every `CLAUDE.md` in the workspace is now under 120 effective lines except the workspace root at 142,
|
||||
which is deliberate: it is the only file re-injected after `/compact`.
|
||||
|
||||
---
|
||||
|
||||
## H. Observations — noticed, not acted on
|
||||
|
||||
1. **R-129 has fresh evidence.** `target-selection.md` records that demo-hp has no baked SSH key and
|
||||
needs G1 break-glass, "but a key authenticated on 2026-07-31 — R-129, unresolved". **A key
|
||||
authenticated again today, 2026-08-06**, non-interactively (`BatchMode=yes`) from DooPlex — that is
|
||||
how the t740 evidence in §E was gathered. The row is still right to be open, and now has a second
|
||||
dated observation.
|
||||
2. **`~/.ssh/config` carries the same expired vacation claim** the memory index did: *"demo-hp … at
|
||||
the VACATION site until ~2026-08-02, LAN 192.168.0.87 there"*. It is host state, outside every
|
||||
repo and outside this task's scope, but it is the same statement in a third place.
|
||||
3. **The hub's operator UI did not answer over its ClusterIP** during this session (request hung,
|
||||
2 min timeout) — the off-site evidence was gathered from the boxes instead. Not investigated;
|
||||
the memory note describing that access path may need re-checking.
|
||||
4. **`MEMORY.md`'s header still reads "felhom-controller Project Memory"** though it indexes all four
|
||||
repos plus the homelab. Cosmetic, left for the R-230(a) ruling.
|
||||
5. **`register_state` is now a reusable register parser** living in the gate. If anything else ever
|
||||
needs "is R-nnn open", it should call this rather than re-deriving it — the two parsing traps in
|
||||
§C are not obvious and were both found the hard way.
|
||||
@@ -113,8 +113,8 @@ the fault was real. Full observables: `tests/campaign11-evidence-2026-08-05/jour
|
||||
|
||||
| ID | What | State |
|
||||
|---|---|---|
|
||||
| **R-229** | **The instruction-file rightsizing landed for `felhom-controller` and the workspace root; three pieces were deliberately deferred.** Done 2026-08-06: controller split into a 92-effective-line core plus four `paths:`-scoped `.claude/rules/*.md`; workspace root 208→142 effective lines with its versioned copy kept byte-identical; surgical corrections to `felhom-agent` and `felhom.eu` (expired TEMPORARY block, every version literal, the Legacy-Windows copies, the duplicated health-check rule); five contradictions resolved — including a drill-VM claim **measured live** (`qm list` on demo-hp shows VM 300 `drill-r50`; `felhom-agent` was right, `felhom-controller` was wrong); new shared `felhom.eu/scripts/instructions_gate.py` registered in `controller_gates.py` and `agent_gates.py`, 20 fixture tests + red-proof. **Leg (a) CLOSED 2026-08-06 (part 2):** `felhom.eu/CLAUDE.md` **227 → 115 effective lines**, split into a core plus `.claude/rules/{hub,website,manifests,docs}.md`; `instructions_gate` **registered in `scripts/repo_gates.py`** (six gates, all OK) in the required order — trim first, register second, because a registered-but-failing gate refuses every push. Scoping proven from the `InstructionsLoaded` hook log in two fresh sessions, not from frontmatter. **Still deferred:** (b) **`felhom-agent/CLAUDE.md` at 173 effective lines** passes with the least headroom; its release section is the next candidate for the `felhom-build-deploy` skill. (c) **CLOSED 2026-08-06 (part 2)** — all 44 orphans resolved with **zero deletions** (file count 158 before and after): 4 durable `reference`-type files indexed, 40 dated episode records moved to `.claude-memory/archive/`. `MEMORY.md` 145 → **150 lines / 17,977 bytes**, and `instructions_gate` check 6 now watches it (over-limit FAILS, orphan WARNS, absent store PASSES *printing its reason*). (d) **The spec-as-failing-test pilot** — moved to R-230. Full accounting: `audits/LEDGER-instruction-trim-2026-08-06.md` + `audits/LEDGER-instruction-trim-part2-2026-08-06.md` | **READY** — owner Viktor |
|
||||
| **R-230** | **Three instruction/memory follow-ups deliberately left by the part-2 session (2026-08-06), each needing a decision rather than an implementation.** (a) **A ruling is owed on auto-written staleness.** The hand-written `CLAUDE.md` files are now clean of version literals and expired blocks — the gate enforces it — but `MEMORY.md`, which Claude writes and which is the LARGER half of what loads (8.4k tokens vs the root file's 6.6k), carries **21 lines with component version literals**, **5 with bare host addresses**, and an entry still reading *"demo boxes REMOTE till ~08-02"* — the same expired-TEMPORARY class the gate was built to kill, now surviving in the one file the gate's content rules do not cover. Diagnosed and **deliberately not edited**: nobody has ruled on how to correct Claude's own notes at scale. (b) **The symlink decision** for the workspace-root `CLAUDE.md`. Now that `install_workspace.py` exists, making the live file a symlink to `documentation/runbooks/workspace-CLAUDE.md` would remove the divergence class outright. **Recommended, not done** — it changes what check 5 is checking (identity of two files becomes correctness of one link), so it needs its own change. (c) **The spec-as-failing-test pilot**, approved in principle and not started (was R-229(d)). | **READY** — owner Viktor |
|
||||
| **R-229** | **The instruction-file rightsizing landed for `felhom-controller` and the workspace root; three pieces were deliberately deferred.** Done 2026-08-06: controller split into a 92-effective-line core plus four `paths:`-scoped `.claude/rules/*.md`; workspace root 208→142 effective lines with its versioned copy kept byte-identical; surgical corrections to `felhom-agent` and `felhom.eu` (expired TEMPORARY block, every version literal, the Legacy-Windows copies, the duplicated health-check rule); five contradictions resolved — including a drill-VM claim **measured live** (`qm list` on demo-hp shows VM 300 `drill-r50`; `felhom-agent` was right, `felhom-controller` was wrong); new shared `felhom.eu/scripts/instructions_gate.py` registered in `controller_gates.py` and `agent_gates.py`, 20 fixture tests + red-proof. **Leg (a) CLOSED 2026-08-06 (part 2):** `felhom.eu/CLAUDE.md` **227 → 115 effective lines**, split into a core plus `.claude/rules/{hub,website,manifests,docs}.md`; `instructions_gate` **registered in `scripts/repo_gates.py`** (six gates, all OK) in the required order — trim first, register second, because a registered-but-failing gate refuses every push. Scoping proven from the `InstructionsLoaded` hook log in two fresh sessions, not from frontmatter. **Still deferred:** (b) **CLOSED 2026-08-06 (close-out)** — `felhom-agent/CLAUDE.md` **175 → 99 effective lines** (measured 175, not 173: the CI correction added two), split into a core plus `.claude/rules/{proxmox,localapi,backup,storage}.md` beside the existing `health-checks.md`. The release section now points at the `felhom-build-deploy` skill instead of restating a table that drifts from the script. **Every `CLAUDE.md` in the workspace is now ≤120 effective lines except the workspace root at 142, which is deliberate — it is the only file re-injected after `/compact`.** (c) **CLOSED 2026-08-06 (part 2)** — all 44 orphans resolved with **zero deletions** (file count 158 before and after): 4 durable `reference`-type files indexed, 40 dated episode records moved to `.claude-memory/archive/`. `MEMORY.md` 145 → **150 lines / 17,977 bytes**, and `instructions_gate` check 6 now watches it (over-limit FAILS, orphan WARNS, absent store PASSES *printing its reason*). (d) **The spec-as-failing-test pilot** — moved to R-230. Full accounting: `audits/LEDGER-instruction-trim-2026-08-06.md` + `audits/LEDGER-instruction-trim-part2-2026-08-06.md` | **READY** — owner Viktor |
|
||||
| **R-230** | **Three instruction/memory follow-ups deliberately left by the part-2 session (2026-08-06), each needing a decision rather than an implementation.** (a) **A ruling is owed on auto-written staleness.** The hand-written `CLAUDE.md` files are now clean of version literals and expired blocks — the gate enforces it — but `MEMORY.md`, which Claude writes and which is the LARGER half of what loads (8.4k tokens vs the root file's 6.6k), carries **21 lines with component version literals**, **5 with bare host addresses**, and an entry still reading *"demo boxes REMOTE till ~08-02"* — the same expired-TEMPORARY class the gate was built to kill, now surviving in the one file the gate's content rules do not cover. **Partly actioned 2026-08-06 (close-out), and the ruling is STILL OWED:** the **three statements that were actively false** were corrected — `R-193 decision open` (closed 2026-08-05), `demo boxes REMOTE till ~08-02` (the box answers on the home LAN), `OPEN R-25b` (shipped 2026-07-21) — and gate check 6 now **WARNs** on version literals, host addresses, expired statements and stale-open citations in the index. WARN, never FAIL: Claude writes that file between sessions, so a hard failure would refuse a human's push over a line no human typed, and the warning is read by the model that will next edit it. **The remaining 32 version literals and 4 host addresses were deliberately left** for that loop. What is still owed is the bulk-correction ruling. **Correcting the premise:** the earlier report's "three expired statements" were all FALSE POSITIVES — each matched an ISO date inside a markdown link target, i.e. a filename — while the one real expired claim carried no ISO date at all. (b) **CLOSED 2026-08-06 (close-out)** — the workspace-root `CLAUDE.md` **is now a relative symlink** to the versioned copy, so the divergence class is gone rather than policed. Check 5 learned two shapes: for a link it asserts the target resolves to a real file (**a dangling link is worse than a diverged copy — the instructions load NOTHING and there is no content left to notice is wrong**), for two files byte-identity as before, so a clone elsewhere is unaffected. **Proven, not assumed:** three fresh sessions logged `session_start` for the link path, and a fourth **with no tools at all** quoted standing rule 1 verbatim — the content reaches the model, not just the path. (c) **The spec-as-failing-test pilot**, approved in principle and not started (was R-229(d)). | **READY** — owner Viktor |
|
||||
| **R-231** | **`/opt/backup/scripts/` on DooPlex is unversioned host state** — found 2026-08-06 while adding the auto-memory store to the backup set. No repository tracks the scripts that protect the recovery chain, so the edit made that day (`CLAUDE_MEMORY_DIR` in `backup-config.sh`, multi-path restic call in `backup-data.sh`) exists only on the box. This is the same class the part-2 session was closing, found inside the fix for it; the change is transcribed in `felhom.eu/workspace/README.md` so it is at least *recorded*. **Two related facts, both understating current safety:** the backup destination (`/mnt/5_hdd/backup`) is on the **same physical disk** as the workspace it protects, and the DooPlex backup set has **no off-site leg** (`sync-hetzner-backups.sh` is jarrs.eu and pulls *from* Hetzner *to* DooPlex). Bringing a root-owned production backup script under version control, and deciding what installs it, is its own scoped change. | **READY** — owner Viktor |
|
||||
|
||||
**Recorded against existing rows by Phase 2:**
|
||||
|
||||
@@ -68,8 +68,34 @@ felhom-pve, and **moved off DooPlex**. This page exists because that ruling sat
|
||||
### `demo-felhom` — N100 · **Tier 0**
|
||||
|
||||
- **Freely:** create/destroy guests and scratch customers; reinstall the box.
|
||||
- **Care:** it carries the **PBS-DR / offsite tier** (demo-hp has none), so it is the Tier 0 box whose
|
||||
backup chain a test can actually disturb. Prefer demo-hp, per the 2026-07-25 ruling.
|
||||
- **Care:** it carries the **PBS-DR / offsite tier** — but so does demo-hp now, so this is **no longer
|
||||
a reason to prefer one over the other**. Prefer demo-hp per the 2026-07-25 ruling, on the ruling's
|
||||
own grounds (it is the designated drill host), not because its backup chain is safe to disturb.
|
||||
|
||||
<!--
|
||||
CORRECTED 2026-08-06. This line used to read "(demo-hp has none)" and was the runbook's stated reason
|
||||
for steering backup-disturbing tests at demo-felhom. It was TRUE WHEN WRITTEN and went stale when F10
|
||||
resolved on 2026-07-23; it was flagged as wrong for some time and carried anyway.
|
||||
|
||||
Measured before editing, on the box, from the tier's own evidence rather than a config entry:
|
||||
|
||||
demo-hp:/etc/pve/storage.cfg pbs: felhom-pbs -> datastore felhom-offsite, server 10.77.0.1,
|
||||
namespace demo-hp, username felhom@pbs!demo-hp
|
||||
demo-hp# LC_ALL=C pvesm list felhom-pbs
|
||||
felhom-pbs:backup/ct/9201/2026-07-28T19:19:45Z pbs-ct 6264034048 9201
|
||||
felhom-pbs:backup/ct/9201/2026-08-04T19:24:16Z pbs-ct 4637840512 9201
|
||||
ep0:/mnt/pbs-datastore/ns/ c11 demo-felhom demo-hp rewalk
|
||||
|
||||
Two snapshots, the newest two days old, in demo-hp's OWN namespace on the shared off-site datastore.
|
||||
The PBS-DR leg is what was measured here; the restic/offbox app-data leg is separately evidenced by
|
||||
R-193, whose whole subject is demo-hp's off-site app-data tier being dropped by the 2026-08-03
|
||||
rebuild and restaged.
|
||||
|
||||
Why this mattered more than a typo: this file's job is to say which machine may be destroyed, and the
|
||||
sentence was load-bearing for that judgement — "its backup chain is not disturbable" is exactly the
|
||||
kind of belief under which a drill lands somewhere it should not.
|
||||
-->
|
||||
|
||||
|
||||
**Both Tier 0 boxes — the shared backup-target fence is DOWNGRADED to a cost, 2026-08-02 (D-d).** It
|
||||
read *"do not re-point either backup target"*, because these are the only two **correctly configured**
|
||||
|
||||
Reference in New Issue
Block a user