#!/bin/sh
# nucleic-bootdebug.sh — one boot-health snapshot to the serial console (docs/LINUX_VM.md
# §Debugging a failed base build).
#
# The host's only always-available window into the guest is the serial console log (provision.log
# during the base build, console.log for a clone). When the vsock agent never comes up the host
# cannot exec anything in the guest, so this unit pushes the diagnosis OUT: shortly after
# multi-user it writes a compact snapshot of the control-plane state to /dev/hvc0. One line when
# healthy; the module/agent/journal state when not. With /etc/nucleic-debug baked in (the host's
# base-build debug switch), the full snapshot is emitted even when healthy, plus a journal tail.

CON=/dev/hvc0
DEBUG=""
[ -f /etc/nucleic-debug ] && DEBUG=1

say() { echo "[nucleic-bootdebug] $*"; [ -w "$CON" ] && echo "[nucleic-bootdebug] $*" > "$CON" 2>/dev/null; }

# Give the agent a moment to settle (it restarts every second while vsock is missing). Type=simple,
# so this sleep delays nothing else in the boot.
sleep 15

agent_state="$(systemctl is-active nucleic-linux-agent.service 2>/dev/null)"
vsock_ok=""
[ -e /dev/vsock ] && vsock_ok=1

if [ "$agent_state" = active ] && [ -n "$vsock_ok" ] && [ -z "$DEBUG" ]; then
    say "OK: agent active, /dev/vsock present ($(uname -r))"
    exit 0
fi

say "=== boot health snapshot ==="
say "uname -r: $(uname -r) (passthrough: $(NAROS_UNAME_PASSTHROUGH=1 uname -r 2>/dev/null))"
say "/lib/modules: $(ls /lib/modules 2>/dev/null | tr '\n' ' ')"
say "/dev/vsock: $([ -e /dev/vsock ] && echo present || echo MISSING)"
say "vsock modules: $(lsmod 2>/dev/null | grep -i vsock | tr '\n' '; ')"
for u in nucleic-modsetup nucleic-linux-agent nucleic-firstboot; do
    say "$u: $(systemctl is-active "$u.service" 2>/dev/null) / $(systemctl is-failed "$u.service" 2>/dev/null)"
done
say "provisioned flag: $([ -f /var/lib/nucleic/provisioned ] && echo present || echo absent)"
journalctl -u nucleic-modsetup.service -u nucleic-linux-agent.service --no-pager -n 25 2>/dev/null \
    | while IFS= read -r line; do say "journal: $line"; done
say "=== end snapshot ==="
exit 0
