otbr has had Thread `disabled` since 2026-06-27. `ot-ctl dataset active`
returns NEST-PAN-339C, the seed Job completed 61 days ago, the RCP answers
(OPENTHREAD/1.3.0.1; CC13XX_CC26XX) -- and the stack was simply never
brought up. The pod had 0 restarts, so it never got a second chance.
The entrypoint waits for `ot-ctl state` to answer, then checks for a
persisted dataset exactly once. otbr-agent answers `state` as soon as its
control socket exists, which is before it has restored the dataset from
/var/lib/thread. The check races the restore and loses:
otbr: no persisted dataset; awaiting bootstrap Job
...after which nothing ever calls `ifconfig up` / `thread start`, because
the seed Job only activates Thread on a clean install. Reproduced exactly
on a restart today, before this fix.
Poll the dataset check for up to 60s instead. Then poll `ot-ctl state`
after `thread start` and log the attach result: `thread start` returns
before MLE has attached, so its exit code proves nothing, and a silent
`disabled` is precisely the failure this block exists to prevent.
Note the `|| true` and the `case` rather than a `[ ... ] && [ ... ] && echo`
chain: this script runs under `set -euo pipefail`, so a bare failing test as
the last statement would kill the container instead of logging a warning.
Verified: `bash -n` clean on the extracted script, `kubectl kustomize`
builds. Merging restarts the pod, which is the real test -- the entrypoint
should now log "persisted dataset found after N attempt(s); activating
Thread" followed by "Thread attached as <state>".
Unrelated but confirmed in passing on today's restart: otbr took its DHCP
lease cleanly under #135/#137 (net1=10.2.30.129, single v4 default via eth0,
sbr rule `from 10.2.30.129 lookup 100`).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>