The log said '(re)loaded'. The brain was down.
Verifying the shipped brain end-to-end caught a green lie: the app reported the brain service '(re)loaded' while it was actually down, because launchctl bootout is async and the success was reported from issuing the command, not from the service loading.
What "verify it properly" turned up
The founder's instruction was blunt: build it, install it, confirm the brain actually runs — verify
it properly. So I did the full shipped path: build the app, swap it into /Applications, clear the
WebView cache, launch.
runtime.log looked great:
INFO ai_brain: brain LaunchAgent (re)loaded → 127.0.0.1:8757Then /health returned nothing. launchctl print gui/$uid/ai.ddalkkak.brain showed no job loaded.
No brain process existed. The log was lying.
Why it lied
Installing the new app migrates the brain from the dev-repo venv to the shipped app-data location —
a new plist path. ai_brain_start handles that by:
bootout (old job) → bootstrap (new plist)But launchctl bootout is asynchronous. The old job — and its hold on port 8757 — lingered for
a beat after bootout returned, so the immediate bootstrap failed. The fallback was a
kickstart -k on a service that was no longer loaded (a no-op), and then:
Ok(format!("brain LaunchAgent (re)loaded ... ")) // returned regardless of successThe function reported success because it had issued the commands, not because the service was
loaded. A manual bootout (→ "No such process", i.e. already gone) + bootstrap (exit 0) seconds
later brought it up cleanly — confirming the venv and code were fine all along. Only the load raced.
The one honest signal in the system was the ⚠️ keyword status badge, which polls /health — it
would have shown down. But the log contradicted it, which is its own bug: two observability surfaces
disagreeing is worse than one.
The fix
ai_brain_start now loops bootout → wait → bootstrap with backoff (up to 6 tries), returns Ok
only when bootstrap actually succeeds, and returns Err otherwise (logged as a real failure, not a
green "(re)loaded"). The race only fires on a plist-changing migration; steady-state launches hit
the loaded && unchanged early-return and never touch launchctl.
Verified — the brain runs from the shipped path
launchctl print→state = running,pid = 33587./health→model_loaded: true(twice, 3s apart)./embed→ 2 rows, dim 384.- The process runs
…/Application Support/DalkkakAI/ai-brain/server.py— the app-data copy seeded from the bundle, not the dev repo. That's the path a shipped user gets. cargo check0 on the fix.
The lesson
A status reporter must derive from the post-condition, not the attempt. "I ran the command" is not
"it worked" — especially when the command is async. Either confirm the post-condition (is it
loaded? does /health answer?) before claiming success, or propagate the real error. The whole
reason to build-install-and-check by hand instead of trusting a green log is that a green log can be
exactly this wrong.