The composition seam between the substrate's planning surface
(slices 5-11) and the headless boot loop (slice 13).
`spawn_persona_service(hosted, runtime, opts, rt_handle)`:
1. Up-cast the persona's `Arc<Airc>` to `Arc<dyn
AircTranscriptReader>` for the RAG layer (zero-cost — same
pointer, different vtable view; impl already exists at
`airc_source.rs:74`).
2. Wrap `Arc<PersonaAircRuntime>` in `AircPersonaConversation`
(slice 11) — production conversation that knows how to talk
to the live daemon.
3. `rt_handle.spawn(serve_persona_loop(hosted, &mut conversation,
reader, opts))` — slice 10's loop runs on the caller's tokio
pool.
Returns a `JoinHandle<Result<ServeOutcome, String>>` so the slice-13
boot path can collect handles for graceful shutdown (.abort() on
server stop, or just .await for steady-state ServeOutcome capture).
Net-additive — does NOT touch the existing IPC boot loop. Slice 13
rewires `crate::ipc::start_server` (~line 1024) so that after
`bootstrap_one(&intent)` succeeds, the boot path builds the
inference profile + adapter + HostedPersona and calls
`spawn_persona_service` to start hosting the persona. Splitting the
helper from the wire-up keeps each commit reviewable.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Summary
spawn_persona_service(hosted, runtime, opts, rt_handle) -> JoinHandle<Result<ServeOutcome, String>>— the composition seam between the substrate's planning surface (slices 5-11, merged in feat(persona): citizen substrate + cognition cache hierarchy foundation (slices 1-6) #1507) and the headless boot loop.crate::ipc::start_server's existing bootstrap loop. Slice 13 wires this helper into the boot path.Arc<Airc>toArc<dyn AircTranscriptReader>(zero-cost; impl atairc_source.rs:74), constructAircPersonaConversation,rt_handle.spawn(serve_persona_loop(...)).Doctrine
Arc<PersonaAircRuntime>+ airc-lib sockets — no stdin/stdout.Handle; no hidden thread spawns.JoinHandleresolves withErr(message)fromserve_persona_loopfailures; no implicit retry / no substitution.Why split helper from wire-up
The helper is a 3-line composition; the wire-up (slice 13) rewrites the IPC boot loop at
~ipc/mod.rs:1024to:bootstrap_one(&intent)succeeds, build the inference profile viabuild_profile(slice 5).LlamaCppPersonaAdapterFactory(slice 9).HostedPersona(slice 9).spawn_persona_service(this PR) to start hosting.JoinHandles for graceful shutdown.That's a load-bearing boot-flow rewrite. Splitting keeps each commit reviewable — this PR is the unit-testable composition seam; slice 13 is the consumer.
Reference docs
src/workers/continuum-core/src/persona/host.rs(new),src/workers/continuum-core/src/persona/mod.rs(registers the module)Test plan
cargo build --bin airc_chat_demo --no-default-features --features livekit-webrtc,accelerate,llama/mac-cpu-only,load-dynamic-ortpasses (verified locally before push)cargo test --lib persona::slice-related modules stay green (verified locally — service_loop, supervisor, spawner, spawner_module all pass)spawn_persona_serviceitself — composition is 3 lines, types check; integration test happens via slice 13's IPC boot pathpersona::allocator::test_allocate_no_keysfailure on canary is tracked separately (task Build(deps-dev): Bump @types/node from 22.14.0 to 24.7.0 #138), unrelated to this PR🤖 Generated with Claude Code