A merged PR may require knowledge-base updates. Review the change and update library/ as needed.
Source PR
- PR: #301 - fix: embed daemon liveness probe, honest health states, recall fast-skip when not warm
- Author: @thenotoriousllama
- Merged into:
main
- Files changed: 19
PR description
Summary
Fixes ISS-007/ISS-008: the embed daemon (:3851) could wedge — accept TCP, never reply (event-loop-blocked inference) — while /health kept reporting embeddings on from a one-shot warm latch in the supervisor. Recall then silently degraded to lexical, every search burned the full bounded embed deadline (fast 1.5s / heavy 3s), and doctor — whose only sensor is /health — stayed blind to the whole chain.
Designed for all three live observations from the dogfood box: (a) a wedge while running, (b) the ~40s post-external-respawn warmup tail (embeds at 10–27s before settling to ~25ms) where a binary alive/dead probe would flap, (c) an externally respawned child never being marked warm by the supervisor's spawn-path-only warmup.
Changes
1. Supervisor liveness (src/daemon/runtime/services/embed-supervisor.ts)
- Periodic bounded liveness probe after warm (default 30s cadence, 2s probe timeout, unref'd-timer scheduler seam) + on-demand
checkNow().
- State machine
warming → warm → suspect → failed: one missed probe → suspect (no flap), a second consecutive miss confirms the wedge → mark not-warm, kill, respawn via the existing bounded crash-restart machinery; the fresh child re-warms through warming (absorbs the 40s tail — no flap).
- Non-reentrant + coalesced probing; additive optional
suspect/state/checkNow on the EmbedSupervisor contract (structural fakes unaffected).
2. /health honesty (src/daemon/runtime/health.ts, assemble.ts)
reasons.embeddings is no longer "known at assembly": it derives from the supervisor's current state per health call and additively gains warming/suspect/failed — not-warm → never on. embeddingsState gains suspect.
- Additive for both consumers: doctor's health-probe parses
reasons.embeddings as a plain string (un-blinded with zero doctor changes); the Hive dashboard prefers embeddingsState (parses warming/failed; zod `.ca
Files touched
.claude-plugin/marketplace.json (+2/-2)
.claude-plugin/plugin.json (+1/-1)
CHANGELOG.md (+4/-0)
embeddings/src/index.ts (+92/-1)
harnesses/claude-code/.claude-plugin/plugin.json (+1/-1)
harnesses/codex/package.json (+1/-1)
harnesses/openclaw/openclaw.plugin.json (+1/-1)
harnesses/openclaw/package.json (+1/-1)
package-lock.json (+2/-2)
package.json (+1/-1)
src/daemon/runtime/assemble.ts (+20/-2)
src/daemon/runtime/health.ts (+67/-28)
src/daemon/runtime/memories/api.ts (+15/-0)
src/daemon/runtime/memories/recall.ts (+123/-27)
src/daemon/runtime/services/embed-supervisor.ts (+210/-0)
tests/daemon/runtime/health.test.ts (+40/-3)
tests/daemon/runtime/memories/recall-embed-gate.test.ts (+272/-0)
tests/daemon/runtime/services/embed-supervisor.test.ts (+272/-0)
tests/embeddings/embed-daemon.test.ts (+99/-0)
Auto-generated by .github/workflows/kb-issue-on-merge.yaml on merge.
A merged PR may require knowledge-base updates. Review the change and update
library/as needed.Source PR
mainPR description
Summary
Fixes ISS-007/ISS-008: the embed daemon (:3851) could wedge — accept TCP, never reply (event-loop-blocked inference) — while
/healthkept reporting embeddingsonfrom a one-shot warm latch in the supervisor. Recall then silently degraded to lexical, every search burned the full bounded embed deadline (fast 1.5s / heavy 3s), and doctor — whose only sensor is/health— stayed blind to the whole chain.Designed for all three live observations from the dogfood box: (a) a wedge while running, (b) the ~40s post-external-respawn warmup tail (embeds at 10–27s before settling to ~25ms) where a binary alive/dead probe would flap, (c) an externally respawned child never being marked warm by the supervisor's spawn-path-only warmup.
Changes
1. Supervisor liveness (
src/daemon/runtime/services/embed-supervisor.ts)checkNow().warming → warm → suspect → failed: one missed probe →suspect(no flap), a second consecutive miss confirms the wedge → mark not-warm, kill, respawn via the existing bounded crash-restart machinery; the fresh child re-warms throughwarming(absorbs the 40s tail — no flap).suspect/state/checkNowon theEmbedSupervisorcontract (structural fakes unaffected).2.
/healthhonesty (src/daemon/runtime/health.ts,assemble.ts)reasons.embeddingsis no longer "known at assembly": it derives from the supervisor's current state per health call and additively gainswarming/suspect/failed— not-warm → neveron.embeddingsStategainssuspect.reasons.embeddingsas a plain string (un-blinded with zero doctor changes); the Hive dashboard prefersembeddingsState(parseswarming/failed; zod `.caFiles touched
.claude-plugin/marketplace.json(+2/-2).claude-plugin/plugin.json(+1/-1)CHANGELOG.md(+4/-0)embeddings/src/index.ts(+92/-1)harnesses/claude-code/.claude-plugin/plugin.json(+1/-1)harnesses/codex/package.json(+1/-1)harnesses/openclaw/openclaw.plugin.json(+1/-1)harnesses/openclaw/package.json(+1/-1)package-lock.json(+2/-2)package.json(+1/-1)src/daemon/runtime/assemble.ts(+20/-2)src/daemon/runtime/health.ts(+67/-28)src/daemon/runtime/memories/api.ts(+15/-0)src/daemon/runtime/memories/recall.ts(+123/-27)src/daemon/runtime/services/embed-supervisor.ts(+210/-0)tests/daemon/runtime/health.test.ts(+40/-3)tests/daemon/runtime/memories/recall-embed-gate.test.ts(+272/-0)tests/daemon/runtime/services/embed-supervisor.test.ts(+272/-0)tests/embeddings/embed-daemon.test.ts(+99/-0)Auto-generated by
.github/workflows/kb-issue-on-merge.yamlon merge.