Links the real EmbeddedDaemon into the ObsidianDragonTests target (its deps were
already present) and adds two POSIX integration tests that exercise the actual
fork/exec/waitpid fixes headlessly:
- testExecFailureReported (F2): start() against a non-executable file must fail with a
precise "not executable or wrong architecture" reason.
- testDaemonCrashDetected (F1): a short-lived child that exits abnormally is still
detected (crash_count_ increments) while isRunning() is hammered from the test
thread — a regression test for the reap race.
Writing the F2 test surfaced a real bug: start()'s failure branch called
setState(State::Error, "Failed to start dragonxd process"), and setState stores the
Error message into last_error_ — clobbering the precise message startProcess() had
just set, so getLastError()/the UI only ever saw the generic string. Fixed to pass the
preserved detail to setState, so the precise reason survives and now also reaches the
state callback (crash panel / status).
ctest 1/1, green including the two new integration tests.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>