QA Team — found during the 2026-07-14 ~17:45Z sweep. Filed against closed#539 (dreamstream6 down since ~16:30Z 2026-07-13, closed 2026-07-14 09:40).
#539 was closed on the node coming back — and the node genuinely is back (docker node ls shows dreamstream6 Ready/Active, and it is serving swarm tasks). But the Gitea act_runner that lives on it never recovered, and nothing noticed, because a dead CI runner does not page anyone; jobs just quietly queue onto the survivors.
Image, env and registration token are byte-identical to the healthy arm_v8_1, so this is not a config-drift or bad-token problem — the spec is fine. What differs is that v8_2 depends on files that live on ds6's local disk, and ds6 is precisely the node that went down hard in #539. act_runner exits 1 at startup when /config.yaml is unreadable or its /data/.runner registration state is missing/corrupt, which is exactly what you would expect if that host path did not survive the outage.
I could not confirm the filesystem state directly — there is no SSH from the manager to ds6 (Permission denied (publickey)), and I did not want to create a probe service to poke at it. Someone with node access should check /home/joey/Docker/gitea-act-runner/ on ds6 — that will settle it in about ten seconds.
Why this matters
ARM CI capacity is 3 runners → 2, silently, since yesterday. Every ubuntu-arm job in every repo now contends for ds5 and ds7.
It makes ARM job queueing and flakiness worse, which muddies the water on unrelated CI bugs (see the IPv6 base-image failure filed alongside this).
Fix
Short term: restore the config + registration state on ds6, or just re-register the runner.
Better: move arm_v8_2 (and arm_v8_1) onto named volumes like arm_v8_3 already uses. Host bind-mounted runner state is the reason a node reboot turns into a permanently dead runner. arm_v8_3 survived on the same class of hardware because its state is in a volume; the other two are one bad reboot away from this exact ticket.
Also worth considering: an alert when any gitea-runners_* service sits at 0/1, since a dead runner is invisible by design.
**QA Team** — found during the 2026-07-14 ~17:45Z sweep. Filed against **closed #539** (*dreamstream6 down since ~16:30Z 2026-07-13*, closed 2026-07-14 09:40).
#539 was closed on the node coming back — and the node genuinely is back (`docker node ls` shows dreamstream6 `Ready`/`Active`, and it is serving swarm tasks). But **the Gitea act_runner that lives on it never recovered**, and nothing noticed, because a dead CI runner does not page anyone; jobs just quietly queue onto the survivors.
## Evidence
```
$ docker service ls --filter name=gitea-runners
gitea-runners_amd64_4090_2_act_runner 1/1
gitea-runners_amd64_4090_act_runner 1/1
gitea-runners_amd64_laptop_act_runner 1/1
gitea-runners_arm_v8_1_act_runner 1/1
gitea-runners_arm_v8_2_act_runner 0/1 <-- dead
gitea-runners_arm_v8_3_act_runner 1/1
$ docker service ps gitea-runners_arm_v8_2_act_runner --no-trunc
... dreamstream6 Failed "task: non-zero exit (1)"
... dreamstream6 Failed "task: non-zero exit (1)"
... dreamstream6 Failed "task: non-zero exit (1)"
```
It is in a tight crash loop — a fresh exit(1) roughly every 20 seconds, indefinitely.
## Likely cause
`arm_v8_2` is the only ARM runner whose **state is bind-mounted off the ds6 host filesystem**:
| runner | node | `/data` |
|---|---|---|
| `arm_v8_1` | DreamStream5 | bind `/home/joey/Docker/gitea-act-runner/data` |
| `arm_v8_2` | **DreamStream6** | bind `/home/joey/Docker/gitea-act-runner/data` + bind `arm2-config.yaml` |
| `arm_v8_3` | DreamStream7 | **named volume** `gitea-runners_arm3-runner-data` |
Image, env and registration token are byte-identical to the healthy `arm_v8_1`, so this is not a config-drift or bad-token problem — the spec is fine. What differs is that v8_2 depends on files that live on **ds6's local disk**, and ds6 is precisely the node that went down hard in #539. act_runner exits 1 at startup when `/config.yaml` is unreadable or its `/data/.runner` registration state is missing/corrupt, which is exactly what you would expect if that host path did not survive the outage.
I could not confirm the filesystem state directly — there is no SSH from the manager to ds6 (`Permission denied (publickey)`), and I did not want to create a probe service to poke at it. Someone with node access should check `/home/joey/Docker/gitea-act-runner/` on ds6 — that will settle it in about ten seconds.
## Why this matters
- ARM CI capacity is **3 runners → 2**, silently, since yesterday. Every `ubuntu-arm` job in every repo now contends for ds5 and ds7.
- It makes ARM job queueing and flakiness worse, which muddies the water on unrelated CI bugs (see the IPv6 base-image failure filed alongside this).
## Fix
Short term: restore the config + registration state on ds6, or just re-register the runner.
Better: **move `arm_v8_2` (and `arm_v8_1`) onto named volumes like `arm_v8_3` already uses.** Host bind-mounted runner state is the reason a node reboot turns into a permanently dead runner. `arm_v8_3` survived on the same class of hardware because its state is in a volume; the other two are one bad reboot away from this exact ticket.
Also worth considering: an alert when any `gitea-runners_*` service sits at 0/1, since a dead runner is invisible by design.
QA Team — sweep 2026-07-14 ~20:15Z. Still broken, and it lies to the obvious check.
docker service ls showed this at 1/1 during my sweep and I briefly recorded it as recovered. That was wrong, and the way it was wrong is worth writing down:
$ docker service ls --filter name=gitea-runners
gitea-runners_arm_v8_2_act_runner 1/1 <-- looks healthy
$ docker service ps gitea-runners_arm_v8_2_act_runner
dreamstream6 | Starting less than a second ago |
dreamstream6 | Failed 5 seconds ago | "task: non-zero exit (1)"
dreamstream6 | Failed 25 seconds ago | "task: non-zero exit (1)"
dreamstream6 | Failed 45 seconds ago | "task: non-zero exit (1)"
It is flapping, not running — a fresh exit(1) roughly every 20 seconds, indefinitely. Because swarm counts a task in Starting toward the replica count, a docker service ls sampled mid-restart reports 1/1. So the cheapest check anyone would reach for reports this runner as healthy at least some of the time.
Two consequences worth carrying:
Do not verify this ticket with docker service ls. Use docker service ps <svc> and look for the Failed/exit(1) cycle. Same applies to any alert we might add for dead runners — alerting on replica count alone will miss a crash-looping service that restarts fast enough.
ARM CI capacity remains 2 runners, not 3. Every ubuntu-arm job across every repo is still contending for ds5 and ds7, which is also making #580 (the IPv6 base-image flake) hit more often than it otherwise would.
Root cause from the original report is unchanged and still unverified for want of node access: arm_v8_2 is the only ARM runner whose config + registration state is bind-mounted off the ds6 host filesystem (/home/joey/Docker/gitea-act-runner/), and ds6 is the node that went down hard in #539. arm_v8_3 on ds7 uses a named volume and survived. Someone with a shell on ds6 can settle this in ten seconds by checking whether that directory still holds arm2-config.yaml and a valid data/.runner.
**QA Team** — sweep 2026-07-14 ~20:15Z. **Still broken, and it lies to the obvious check.**
`docker service ls` showed this at **1/1** during my sweep and I briefly recorded it as recovered. That was wrong, and the way it was wrong is worth writing down:
```
$ docker service ls --filter name=gitea-runners
gitea-runners_arm_v8_2_act_runner 1/1 <-- looks healthy
$ docker service ps gitea-runners_arm_v8_2_act_runner
dreamstream6 | Starting less than a second ago |
dreamstream6 | Failed 5 seconds ago | "task: non-zero exit (1)"
dreamstream6 | Failed 25 seconds ago | "task: non-zero exit (1)"
dreamstream6 | Failed 45 seconds ago | "task: non-zero exit (1)"
```
It is **flapping**, not running — a fresh exit(1) roughly every 20 seconds, indefinitely. Because swarm counts a task in `Starting` toward the replica count, a `docker service ls` sampled mid-restart reports **1/1**. So the cheapest check anyone would reach for reports this runner as healthy at least some of the time.
Two consequences worth carrying:
- **Do not verify this ticket with `docker service ls`.** Use `docker service ps <svc>` and look for the Failed/exit(1) cycle. Same applies to any alert we might add for dead runners — alerting on replica count alone will miss a crash-looping service that restarts fast enough.
- ARM CI capacity remains **2 runners, not 3**. Every `ubuntu-arm` job across every repo is still contending for ds5 and ds7, which is also making #580 (the IPv6 base-image flake) hit more often than it otherwise would.
Root cause from the original report is unchanged and still unverified for want of node access: `arm_v8_2` is the only ARM runner whose config + registration state is bind-mounted off the ds6 host filesystem (`/home/joey/Docker/gitea-act-runner/`), and ds6 is the node that went down hard in #539. `arm_v8_3` on ds7 uses a **named volume** and survived. Someone with a shell on ds6 can settle this in ten seconds by checking whether that directory still holds `arm2-config.yaml` and a valid `data/.runner`.
gitea-runners_arm_v8_2_act_runner on dreamstream6 is still crash-looping, ~3 days on:
$ docker service ps gitea-runners_arm_v8_2_act_runner
dreamstream6 Running 11 seconds ago
dreamstream6 Failed 19 seconds ago "task: non-zero exit (1)"
dreamstream6 Failed 40 seconds ago "task: non-zero exit (1)"
dreamstream6 Failed about a minute ago "task: non-zero exit (1)"
dreamstream6 Failed about a minute ago "task: non-zero exit (1)"
It exits(1) roughly every 20 seconds and is immediately rescheduled.
⚠️Do not verify this ticket with docker service ls — it will lie to you. It reports 1/1 for this service, because swarm counts a task in Starting toward the replica count. The service looks perfectly healthy in service ls while completing zero work. docker service ps is the only view that shows the truth.
I nearly logged this as recovered for exactly that reason. Flagging it here so the next person doesn't.
Two other runners show historical churn worth a glance, though both are stable now:
gitea-runners_amd64_4090_act_runner — one exit (137) (OOM-kill) 2 days ago.
The exit (137) on the 4090 runner is worth keeping an eye on given that node now also hosts quiz-generation and image-description (both large-VRAM, and image-description's resident footprint is ~18.3 GB). If runner OOM-kills recur there, memory pressure from the co-located GPU workers is the first place to look.
**QA Team — still flapping. Re-verified 2026-07-14.**
`gitea-runners_arm_v8_2_act_runner` on **dreamstream6** is still crash-looping, ~3 days on:
```
$ docker service ps gitea-runners_arm_v8_2_act_runner
dreamstream6 Running 11 seconds ago
dreamstream6 Failed 19 seconds ago "task: non-zero exit (1)"
dreamstream6 Failed 40 seconds ago "task: non-zero exit (1)"
dreamstream6 Failed about a minute ago "task: non-zero exit (1)"
dreamstream6 Failed about a minute ago "task: non-zero exit (1)"
```
It exits(1) roughly every 20 seconds and is immediately rescheduled.
⚠️ **Do not verify this ticket with `docker service ls` — it will lie to you.** It reports `1/1` for this service, because swarm counts a task in `Starting` toward the replica count. The service looks perfectly healthy in `service ls` while completing zero work. `docker service ps` is the only view that shows the truth.
I nearly logged this as recovered for exactly that reason. Flagging it here so the next person doesn't.
Two other runners show historical churn worth a glance, though both are stable *now*:
- `gitea-runners_amd64_laptop_act_runner` — 4× `exit (1)` around 44h ago, running clean since.
- `gitea-runners_amd64_4090_act_runner` — one `exit (137)` (OOM-kill) 2 days ago.
The `exit (137)` on the 4090 runner is worth keeping an eye on given that node now also hosts quiz-generation and image-description (both large-VRAM, and image-description's resident footprint is ~18.3 GB). If runner OOM-kills recur there, memory pressure from the co-located GPU workers is the first place to look.
QA Team — confirming this is still live, and that it is worse than "capacity down 3→2".
gitea-runners_arm_v8_2_act_runner is crash-looping right now on dreamstream6:
task: non-zero exit (1) Failed 14 seconds ago
task: non-zero exit (1) Failed 35 seconds ago
task: non-zero exit (1) Failed 55 seconds ago
task: non-zero exit (1) Failed ~1m ago
Exit(1) roughly every 20 seconds. Note it reported 1/1 in docker service ls on our first check and 0/1 minutes later — it is flapping, not converged, so a green service ls does not clear this ticket.
We could not retrieve its logs: docker service logs fails with node smjf65zries0iyugd9h2pgrml is not available — the manager cannot stream logs from ds6 at all.
The bigger context we hit while investigating
dreamstream1, dreamstream4 and dreamstream6 all report Ready / Active in docker node ls, but are effectively degraded:
the manager cannot stream logs from any of the three
all three reject image pulls (No such image: ...:latest — see our note on #587)
ds6 additionally failed a digest-pinned Docker Hub pull 21 h ago (postgres:16@sha256:be01cf...), which is not explained by the internal-registry tag problem
That last point suggests a node-level pull/disk fault on ds6 on top of the registry issue. We did not have node shell access to confirm — suspect disk-full, which would match the existing build-node disk-cleanup runbook. Worth a node-level check on ds1/4/6 as a follow-up; the arm runner crash-loop may simply be a symptom of it.
**QA Team** — confirming this is still live, and that it is worse than "capacity down 3→2".
`gitea-runners_arm_v8_2_act_runner` is **crash-looping right now** on dreamstream6:
```
task: non-zero exit (1) Failed 14 seconds ago
task: non-zero exit (1) Failed 35 seconds ago
task: non-zero exit (1) Failed 55 seconds ago
task: non-zero exit (1) Failed ~1m ago
```
Exit(1) roughly every **20 seconds**. Note it reported `1/1` in `docker service ls` on our first check and `0/1` minutes later — it is **flapping, not converged**, so a green `service ls` does not clear this ticket.
We could not retrieve its logs: `docker service logs` fails with `node smjf65zries0iyugd9h2pgrml is not available` — the manager cannot stream logs from ds6 at all.
## The bigger context we hit while investigating
dreamstream1, dreamstream4 and dreamstream6 all report `Ready` / `Active` in `docker node ls`, but are effectively **degraded**:
- the manager cannot stream logs from any of the three
- all three reject image pulls (`No such image: ...:latest` — see our note on #587)
- ds6 additionally failed a **digest-pinned Docker Hub** pull 21 h ago (`postgres:16@sha256:be01cf...`), which is *not* explained by the internal-registry tag problem
That last point suggests a **node-level pull/disk fault on ds6 on top of** the registry issue. We did not have node shell access to confirm — **suspect disk-full**, which would match the existing build-node disk-cleanup runbook. Worth a node-level check on ds1/4/6 as a follow-up; the arm runner crash-loop may simply be a symptom of it.
Related: #587 (registry `:latest`), #562, #539 (ds6 previously down).
Noting for the record — this was closed today (2026-07-29 ~15:36Z) with no closing comment, and I'm leaving it closed on the assumption that was deliberate. But the durable fix is definitively absent from origin/master, so if the close was based on ds6 being hand-repaired, the fragility that caused this is unchanged and will recur on the next bad reboot.
What I verified:
The recommended fix was never applied.gitea-act-runner/docker-stack.yml:150-153 still bind-mounts the ds6 host paths for arm_v8_2 — /home/joey/Docker/gitea-act-runner/arm2-config.yaml:/config.yaml and /home/joey/Docker/gitea-act-runner/data:/data:rw. The named-volume migration this ticket recommended did not happen.
arm_v8_1 is on a host bind too (:175), so the "one bad reboot away" exposure applies to both remaining ARM runners, not just the one that broke.
The healthy comparison case was deleted.arm_v8_3 — the runner on a named volume that survived #539 — was removed by 2d519f7 (2026-07-23, "drop ARM runner #3 — ds7 is now the dedicated Keycloak node"). So ARM capacity is now structurally 2, and if arm_v8_2 is still flapping it's effectively 1.
No 0/1 runner alert was added. Which matters more here than usual: this ticket's own comments document that docker service ls reports 1/1 for a service crash-looping every ~20s, because swarm counts a task in Starting toward the replica count. Any alert built on replica count would have the same blind spot the humans did.
git log for gitea-act-runner/ since 07-13 shows only runner-count and image-version changes (6ba6f2a, 2d519f7, d968109) — none referencing this ticket.
If ds6 was repaired by hand, that's fine and this can stay closed — but the two follow-ups worth carrying somewhere are migrate both ARM runners to named volumes and add a runner-liveness alert that uses docker service ps, not service ls. Happy to file those as a separate ticket if you'd rather not reopen this one.
Noting for the record — this was closed today (2026-07-29 ~15:36Z) with no closing comment, and I'm leaving it closed on the assumption that was deliberate. But the **durable fix is definitively absent from `origin/master`**, so if the close was based on ds6 being hand-repaired, the fragility that caused this is unchanged and will recur on the next bad reboot.
What I verified:
- **The recommended fix was never applied.** `gitea-act-runner/docker-stack.yml:150-153` still bind-mounts the ds6 host paths for `arm_v8_2` — `/home/joey/Docker/gitea-act-runner/arm2-config.yaml:/config.yaml` and `/home/joey/Docker/gitea-act-runner/data:/data:rw`. The named-volume migration this ticket recommended did not happen.
- **`arm_v8_1` is on a host bind too** (`:175`), so the "one bad reboot away" exposure applies to both remaining ARM runners, not just the one that broke.
- **The healthy comparison case was deleted.** `arm_v8_3` — the runner on a named volume that survived #539 — was removed by `2d519f7` (2026-07-23, "drop ARM runner #3 — ds7 is now the dedicated Keycloak node"). So ARM capacity is now structurally **2**, and if arm_v8_2 is still flapping it's effectively **1**.
- **No 0/1 runner alert was added.** Which matters more here than usual: this ticket's own comments document that `docker service ls` reports `1/1` for a service crash-looping every ~20s, because swarm counts a task in `Starting` toward the replica count. Any alert built on replica count would have the same blind spot the humans did.
- `git log` for `gitea-act-runner/` since 07-13 shows only runner-count and image-version changes (`6ba6f2a`, `2d519f7`, `d968109`) — none referencing this ticket.
If ds6 was repaired by hand, that's fine and this can stay closed — but the two follow-ups worth carrying somewhere are **migrate both ARM runners to named volumes** and **add a runner-liveness alert that uses `docker service ps`, not `service ls`**. Happy to file those as a separate ticket if you'd rather not reopen this one.
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
QA Team — found during the 2026-07-14 ~17:45Z sweep. Filed against closed #539 (dreamstream6 down since ~16:30Z 2026-07-13, closed 2026-07-14 09:40).
#539 was closed on the node coming back — and the node genuinely is back (
docker node lsshows dreamstream6Ready/Active, and it is serving swarm tasks). But the Gitea act_runner that lives on it never recovered, and nothing noticed, because a dead CI runner does not page anyone; jobs just quietly queue onto the survivors.Evidence
It is in a tight crash loop — a fresh exit(1) roughly every 20 seconds, indefinitely.
Likely cause
arm_v8_2is the only ARM runner whose state is bind-mounted off the ds6 host filesystem:/dataarm_v8_1/home/joey/Docker/gitea-act-runner/dataarm_v8_2/home/joey/Docker/gitea-act-runner/data+ bindarm2-config.yamlarm_v8_3gitea-runners_arm3-runner-dataImage, env and registration token are byte-identical to the healthy
arm_v8_1, so this is not a config-drift or bad-token problem — the spec is fine. What differs is that v8_2 depends on files that live on ds6's local disk, and ds6 is precisely the node that went down hard in #539. act_runner exits 1 at startup when/config.yamlis unreadable or its/data/.runnerregistration state is missing/corrupt, which is exactly what you would expect if that host path did not survive the outage.I could not confirm the filesystem state directly — there is no SSH from the manager to ds6 (
Permission denied (publickey)), and I did not want to create a probe service to poke at it. Someone with node access should check/home/joey/Docker/gitea-act-runner/on ds6 — that will settle it in about ten seconds.Why this matters
ubuntu-armjob in every repo now contends for ds5 and ds7.Fix
Short term: restore the config + registration state on ds6, or just re-register the runner.
Better: move
arm_v8_2(andarm_v8_1) onto named volumes likearm_v8_3already uses. Host bind-mounted runner state is the reason a node reboot turns into a permanently dead runner.arm_v8_3survived on the same class of hardware because its state is in a volume; the other two are one bad reboot away from this exact ticket.Also worth considering: an alert when any
gitea-runners_*service sits at 0/1, since a dead runner is invisible by design.QA Team — sweep 2026-07-14 ~20:15Z. Still broken, and it lies to the obvious check.
docker service lsshowed this at 1/1 during my sweep and I briefly recorded it as recovered. That was wrong, and the way it was wrong is worth writing down:It is flapping, not running — a fresh exit(1) roughly every 20 seconds, indefinitely. Because swarm counts a task in
Startingtoward the replica count, adocker service lssampled mid-restart reports 1/1. So the cheapest check anyone would reach for reports this runner as healthy at least some of the time.Two consequences worth carrying:
docker service ls. Usedocker service ps <svc>and look for the Failed/exit(1) cycle. Same applies to any alert we might add for dead runners — alerting on replica count alone will miss a crash-looping service that restarts fast enough.ubuntu-armjob across every repo is still contending for ds5 and ds7, which is also making #580 (the IPv6 base-image flake) hit more often than it otherwise would.Root cause from the original report is unchanged and still unverified for want of node access:
arm_v8_2is the only ARM runner whose config + registration state is bind-mounted off the ds6 host filesystem (/home/joey/Docker/gitea-act-runner/), and ds6 is the node that went down hard in #539.arm_v8_3on ds7 uses a named volume and survived. Someone with a shell on ds6 can settle this in ten seconds by checking whether that directory still holdsarm2-config.yamland a validdata/.runner.QA Team — still flapping. Re-verified 2026-07-14.
gitea-runners_arm_v8_2_act_runneron dreamstream6 is still crash-looping, ~3 days on:It exits(1) roughly every 20 seconds and is immediately rescheduled.
⚠️ Do not verify this ticket with
docker service ls— it will lie to you. It reports1/1for this service, because swarm counts a task inStartingtoward the replica count. The service looks perfectly healthy inservice lswhile completing zero work.docker service psis the only view that shows the truth.I nearly logged this as recovered for exactly that reason. Flagging it here so the next person doesn't.
Two other runners show historical churn worth a glance, though both are stable now:
gitea-runners_amd64_laptop_act_runner— 4×exit (1)around 44h ago, running clean since.gitea-runners_amd64_4090_act_runner— oneexit (137)(OOM-kill) 2 days ago.The
exit (137)on the 4090 runner is worth keeping an eye on given that node now also hosts quiz-generation and image-description (both large-VRAM, and image-description's resident footprint is ~18.3 GB). If runner OOM-kills recur there, memory pressure from the co-located GPU workers is the first place to look.QA Team — confirming this is still live, and that it is worse than "capacity down 3→2".
gitea-runners_arm_v8_2_act_runneris crash-looping right now on dreamstream6:Exit(1) roughly every 20 seconds. Note it reported
1/1indocker service lson our first check and0/1minutes later — it is flapping, not converged, so a greenservice lsdoes not clear this ticket.We could not retrieve its logs:
docker service logsfails withnode smjf65zries0iyugd9h2pgrml is not available— the manager cannot stream logs from ds6 at all.The bigger context we hit while investigating
dreamstream1, dreamstream4 and dreamstream6 all report
Ready/Activeindocker node ls, but are effectively degraded:No such image: ...:latest— see our note on #587)postgres:16@sha256:be01cf...), which is not explained by the internal-registry tag problemThat last point suggests a node-level pull/disk fault on ds6 on top of the registry issue. We did not have node shell access to confirm — suspect disk-full, which would match the existing build-node disk-cleanup runbook. Worth a node-level check on ds1/4/6 as a follow-up; the arm runner crash-loop may simply be a symptom of it.
Related: #587 (registry
:latest), #562, #539 (ds6 previously down).Noting for the record — this was closed today (2026-07-29 ~15:36Z) with no closing comment, and I'm leaving it closed on the assumption that was deliberate. But the durable fix is definitively absent from
origin/master, so if the close was based on ds6 being hand-repaired, the fragility that caused this is unchanged and will recur on the next bad reboot.What I verified:
gitea-act-runner/docker-stack.yml:150-153still bind-mounts the ds6 host paths forarm_v8_2—/home/joey/Docker/gitea-act-runner/arm2-config.yaml:/config.yamland/home/joey/Docker/gitea-act-runner/data:/data:rw. The named-volume migration this ticket recommended did not happen.arm_v8_1is on a host bind too (:175), so the "one bad reboot away" exposure applies to both remaining ARM runners, not just the one that broke.arm_v8_3— the runner on a named volume that survived #539 — was removed by2d519f7(2026-07-23, "drop ARM runner #3 — ds7 is now the dedicated Keycloak node"). So ARM capacity is now structurally 2, and if arm_v8_2 is still flapping it's effectively 1.docker service lsreports1/1for a service crash-looping every ~20s, because swarm counts a task inStartingtoward the replica count. Any alert built on replica count would have the same blind spot the humans did.git logforgitea-act-runner/since 07-13 shows only runner-count and image-version changes (6ba6f2a,2d519f7,d968109) — none referencing this ticket.If ds6 was repaired by hand, that's fine and this can stay closed — but the two follow-ups worth carrying somewhere are migrate both ARM runners to named volumes and add a runner-liveness alert that uses
docker service ps, notservice ls. Happy to file those as a separate ticket if you'd rather not reopen this one.