Repository navigation
Added
- Guest journey timing and slow-turn tracing:
pod_bridge_backend_wait_seconds,pod_bridge_synthesis_duration_seconds,voice_turn_time_to_first_audio_seconds,voice_tts_first_audio_latency_seconds,property_ticket_resolve_duration_seconds{pack,tool}; a turn whose wait after speech reachesservice.slow_turn_threshold_ms(default 3000) is logged once asslow_turnwith its full stage timeline and counted invoice_slow_turns_total{component,slowest_stage}, withvoice_turn_unaccounted_duration_seconds{component}for time no stage covers. New "Aice Guest Journey" dashboard; Prometheus also scrapespod-gatewayandaice-hotels. - Pod firmware for the Waveshare ESP32-S3-AUDIO-Board (ES8311 speaker, ES7210 mics with a playback echo reference, 7-LED ring, three buttons); the ATOM Echo target is removed. Docs moved to
docs/deployment/pod.md. - The pod sets its clock over NTP before any TLS connection and resolves
.localhost names over mDNS. - Talking over an answer on a full-duplex pod: the pod streams its mic and its playback loopback during answers; the bridge cancels the echo (delay search + NLMS) and stops the answer on speech that clearly beats the predicted echo (
pod_gateway.barge_in_start_level,barge_in_start_frames,barge_in_echo_ratio).pod_bridge_barge_in_total{result},pod_bridge_barge_in_latency_seconds. - Short-term conversation context: the backend keeps the last
memory.max_recent_turnsexchanges per session in memory for chat replies, cleared on a new stay or after 10 idle minutes;playback_interrupted {spoken_ratio}cuts an interrupted answer to what was heard.
Fixed
-
Duration metrics were exported as summaries, so every dashboard panel built on
histogram_quantileover_bucketseries was empty; every*_secondsmetric is now exported as a histogram with fixed buckets (5 ms to 4 h). -
A failed skill (a provider timed out, a place was not found) was silent on the pod; it now says it could not get the information. This now covers every skill (most returned their error past the apology).
-
A pause after "Computer, ..." split one request into fragments ("of Tahini"); speech that goes on before any answer is now sent again together with the first part as one request.
-
The bridge ignores answers for turns it has replaced, so a cancelled turn's empty answer no longer swallows the real one.
-
The horoscope classifier slot is limited to the 12 signs (it took "today" as the sign).
-
A full-duplex pod's last buffered words after an answer were heard as a new request; the bridge waits until the pod's speaker is quiet.
-
Room pods could never make hotel requests: the classifier only offered them to clients that declared
skill_hotel. A backend with a property facilitator now always offers them. -
The classifier's answer was capped at 24 tokens, so hotel requests with details were cut off, failed to parse, and fell back to chat. The cap is 64 (decoding still stops when the JSON is complete).
-
Chat replies could promise actions that never happened ("I'll get you an extra pillow right away"). Chat is now told it cannot act and must say the request could not be sent.
-
Ollama reloaded the model on every call (about 3 s each) because classifier and memory calls asked for a different context size than the warm-up and answers. Calls to a shared host now use one size, so the model loaded at startup stays loaded.
-
Whisper encoded a full 30 s window for every clip; it now encodes only the audio plus a margin, so a short request transcribes about four times faster on the CPU.
-
Staff desk login with
staffandsupervisorroles, CSRF protection, lockout after five failed passwords, and an append-only audit log;user add|remove|liston every pack. -
A service token between backend and facilitator (
service.token,property.service_token_file). -
Room pod provisioning: pods enrol with a nonce, a supervisor assigns the room, the pod receives a device token;
device list|assign|revoke. The backend verifies the token on every connection and turn and takes the room from it. -
TLS from a property-local CA (
crates/core-tls): facilitatortls.mode: auto|files|off, backendservice.tls, bridgepod_gateway.tls;tls fingerprint|issue. -
Stays with private, stay-scoped memory; per-stay memory consent;
memory_retentionkeep(default for hotels and care),archive, orwipe_on_close(default for wards); a backend retention job;stay open|close|list. -
Staff alert tiers, webhook and property-MCP channels, and per-tool SLA re-escalation that survives restarts.
-
Room bridge (
pod-gateway): speech detection, turns on the backend with the pod's token, Piper speech back to the pod paced for its playback queue. -
Device heartbeats and
device_offlinetickets; a help button (long press) that raises a ticket without speech; a privacy mute (double tap). -
Signed pod firmware updates with staged rollout (
firmware keygen|publish|rollout|pod-header) and lost-token recovery. -
Admission control (
service.max_concurrent_turns,service.turn_queue_max_wait_ms), a Whisper worker pool (stt.workers), and LLM host failover (ollama_urls). -
room-loadtestand a CI capacity gate; CI builds the pod firmware; Linux x86_64 and aarch64 release archives. -
Pilot runbook, DPIA template, and clinical safety starter.
Changed
- Memory Palace moves from
mempalace-rustv0.1.0topalace-rsv0.18.0(renamed repositoryAncientiCe/palace-rs, librarypalace), which dropsserde_yamland its unmaintainedunsafe-libyaml(RUSTSEC-2024-0449). Existing palaces are marked with their embedding model on first open; no vectors are rewritten. The default data directory is~/.palace; installs that only have~/.mempalacekeep using it. Stay purges also clear the new wing registry, usage events, mined-file records, and feedback for the stay. - The facilitator refuses plain HTTP off loopback, and a property backend or bridge refuses plain HTTP/WebSocket on a network bind unless
service.allow_plaintext_lanis set. - In a property deployment a turn without an open, consented stay remembers nothing, and the shared journal skill is hidden from rooms.
pod-gatewayis no longer a logging stub; its oldrun_gatewaylibrary API is replaced byspawn_bridge.- Pods take their room from the desk, not from firmware (
DEVICE_ROOMis gone).
Security
- Previously the desk, ticket API and
/mcpwere reachable without credentials, and a room's turn stream accepted any client-supplied room.
Release assets
aice-v0.4.0-macos-arm64.tar.gzand.sha256aice-v0.4.0-linux-x86_64.tar.gzand.sha256aice-v0.4.0-linux-aarch64.tar.gzand.sha256