How it's wired
One monorepo, three compose profiles
Monorepo: apps/server (the FastAPI cos package — routes /
services / storage / shared layers plus a settings.py env loader),
apps/web (the static browser UI), apps/voice-agent (a
separate LiveKit worker with pluggable STT/TTS adapters — scaffolded, idle by default),
nebula-conformance (a public-API conformance runner plus bounded
attestation), and nebula-api (the OpenAPI contract).
Three Docker Compose files keep the default install minimal:
compose.yaml (server only, bound to 127.0.0.1:8080),
compose.local-models.yaml (opt-in llama.cpp overlay), and
compose.voice.yaml (opt-in LiveKit + voice-agent overlay).
The server tells the truth about itself
Live
Contract-first means capabilities.py emits every optional feature as disabled by
default, and a single-writer LIVE-CODE-STATUS ledger tracks each surface as
live / built / gated / aspirational against file-level evidence.
under the hood: apps/server/cos/…/capabilities.py · LIVE-CODE-STATUS ledger