Files
felhom.eu/REPORT.md
T
admin 907e5ce65c docs(TASK-D): R-51/R-52 SHIPPED + new R-54 row; capability-map row; seam-discipline rider
R-51's roadmap diagnosis is corrected at the source: aggregation returned StateRunning
("partial") for a running/stopped mix, so the stack read RUNNING and IsDownState was never
consulted about  at all — the constraint that row protects was never in tension
with the fix.

New R-54 row closes the INCIDENT-guest-dhclient-killed-2026-07-20 §5 OPEN RISK, and records
the design fact that makes it work: liveness of the DHCP client is itself a probe, because
the damage is timed and the address outlives its cause by 1-2 hours. The static-guest leg is
deliberately deferred to R-50.

New capability-map row is IMPLEMENTED, not PROVEN-LIVE: one leg is live (the watchdog's
healthy cycle on felhom-pve), the three that matter are destructive and operator-present and
have not run.

PROMPT-TEMPLATE §10 gains the seam-discipline row, including that a strings.Contains source
assertion is NOT sufficient — a commented-out call still contains the string.
2026-07-21 12:40:00 +02:00

5.7 KiB
Raw Blame History

felhom.eu — task reports

Overwrite this file with a summary of the most recent task only (uniform with the other repos; not cumulative). The cumulative hub history lives in hub/CHANGELOG.md; the scripts history lives in scripts/CHANGELOG.md.


TASK-D — unattended resilience: docs, roadmap, capability map, riders (2026-07-21)

No hub code was touched (§12 of the brief). This repo's share is documentation, the two Part-5 riders, and the honest status of the three claims the task makes.

Implementation reports live in the repos that shipped: felhom-controller/REPORT.md (R-51, R-52, v0.156.0) and felhom-agent/REPORT.md (R-54, v0.92.1).

1. ROADMAP

  • R-51 → SHIPPED (controller v0.156.0), and the row's diagnosis is corrected in place. It claimed aggregation classified a dead-primary stack unhealthy, making the deliberate unhealthy exclusion the suppressor. The source says otherwise: aggregateState's final branch returned StateRunning for any running/stopped mix ("report as running (partial)"), so the stack read running and IsDownState was never consulted about unhealthy at all. The constraint the row protects was therefore never in tension with the fix, and downstate_test.go ships untouched.
  • R-52 → SHIPPED (controller v0.156.0), internal/bootrecon. Note recorded that P1 is not a blocker: the reconciliation is correct whether or not Docker recorded those two containers as user-stopped, and P1's experiment falls out of STOP-1's reboot leg for free.
  • R-54 → NEW ROW, SHIPPED (agent v0.92.1). Origin: INCIDENT-guest-dhclient-killed-2026-07-20 §5, whose OPEN RISK it closes. The row carries the load-bearing design fact — liveness of the DHCP client is itself a probe, because the damage is timed and the address survives the cause by 12 hours — the live sudoers finding, and the explicit deferral of the static-guest leg to R-50, which is where the incident's own option 2 ("give the guest a static address") belongs.

2. Capability map

New row in section: "Box survives an unattended app or guest-network failure" — status IMPLEMENTED, deliberately not PROVEN-LIVE.

One leg genuinely is live and is cited as such: the guest-network watchdog's healthy cycle on felhom-pve (ok=68 total=68 degraded=0 and DEBUG guestnet: guest network healthy vmid=9201 mode=dhcp has_route=true dhclient_alive=true, 12:34:15 CEST). The three legs that would earn PROVEN-LIVE are all destructive and operator-present, and none has run: killing immich's primary, rebooting 9201 to strand and recover boot orphans, and replaying the dhclient kill. The strict enum says a row without that evidence is not PROVEN-LIVE, so it is not.

The existing "Box survives a site/network change" row (PARTIAL) already pointed at R-51/R-52 as related work; it stays PARTIAL — R-50 is still its durable fix.

3. Part-5 riders

  • Hub build.sh deploy hint → GitOps wording. The script printed kubectl set image … and kubectl apply -f manifests/hub.yaml as the deploy instructions — both are reverted by the next ArgoCD sync, which is the worst failure shape: it appears to work, then silently disappears. Now prints the manifest-bump + hard-refresh + deliberate-sync sequence, and names the trap explicitly. Caveat worth knowing: /mnt/5_hdd/felhom.eu/build/felhom-hub/build.sh is NOT in any git repo — it is a DooPlex-local build-dir script. So this rider is a fix to the operative file only, and it is not versioned anywhere. Worth adopting into the repo as its own change.
  • documentation/PROMPT-TEMPLATE.md §10 gains the seam-discipline row. Text generalised from the brief's §9 rule 6, plus what this session added to it: three shipped inert-seam defects in three days (controller v0.154.0, agent v0.91.0, agent v0.92.0's missing sudoers grant), all fully green; and the finding that a strings.Contains source assertion is not sufficient, because a commented-out call still contains the string — walk the AST.

4. What was verified, and how

Endpoint/host-level, no browser (none on DooPlex). Everything claimed live in the two implementation reports was read out of journald or the agent's own capability self-check on felhom-pve. No claim in any of the three reports rests on a test that only proves a seam.

5. An ordering question for the operator (STOP-1 vs STOP-3)

The brief's Phase A says do not hand-deploy the controller — the floor save at STOP-3 is what deploys 0.156.0, banking another single-fire self-update datapoint. But STOP-1 exercises the controller legs, which need 0.156.0 to be live. As written the two are in the wrong order.

The resolution that keeps both intentions is: do the STOP-3 controller floor save first (floor → 0.156.0), let the box self-update — that IS the R-23 datapoint — and then run STOP-1 against the new version. The agent half of STOP-3 (manifest → 0.92.1) is independent and can happen at any point. Flagged rather than assumed, because reordering an operator's STOP sequence is not CC's call.

6. Follow-ups this session surfaced (none actioned here)

  1. felhom-controller/controller/.gitignore's bare controller entry also matches the directory cmd/controller/, so ripgrep silently skips main.go and new files there need git add -f. Both directions produce inert-seam mistakes. XS fix: anchor it as /controller.
  2. The hub build.sh above is unversioned.
  3. TestGenerateRecoveryCode_EntropyAndFormat (agent) flakes on hyphenated wordlist entries (drop-down → 11 tokens). Observed 3/8 this session — worse than the documented ~1/5, and it is a one-line fix in the generator or the assertion, not a mystery.