# Central AI Hub — Code Structure Map > **Writing Style**: ASD-STE100 Simplified Technical English (`ste-writing`). > **Status**: Hub skeleton built (AUD-49). The three inbound routes answer. ## Folder Layout ```text central_ai_llm_master/ AGENTS.md project rules for agents hub_brief.md agreed design (source of truth) README.md technical readme routing.md human-edited routing rules Dockerfile multi-stage build (static binary, distroless) docker-compose.yml one container, port 8788 .dockerignore build context filter docs/ hub-architecture.mmd Mermaid source hub-architecture-map.html Archify map diagrams/ rendered images archify/ Archify JSON input outline/ AI context documents ask-contract.md Hub to project interface hub-api.md frozen inbound API (v1) vikunja-tasks.json human task list scripts/ paperclip-roundtrip.sh Phase 1 outbound job proof src/ Hub service code (module hub) go.mod module hub (Go 1.25, standard library only) main.go HTTP layer: POST /ask, POST /approve, GET /health apierr/ the frozen error envelope ids/ ULID request and approval ids config/ environment and secrets loading hear/ step 1: decode and validate the request understand/ step 2: never-route check and the routing LLM check/ step 3: identity and source checks route/ step 4: dispatch to one destination answer/ step 5: reply shaping (text, speech, notify) destinations/ one client per destination: project.go (a data project through /ask) speakers.go (Jervis house TTS) paperclip.go (file a job after approval) logbook/ append-only, size-capped request log hub/ the pipeline that wires the five steps tests/fakeproject/ fake /ask project for tests and manual runs ``` ## Entry Points | Entry point | Use | Handler | |---|---|---| | `POST /ask` | Send a voice transcript or text. Returns a reply. | `main.go`, `hub.Service.Ask` | | `POST /approve` | Admin app confirms a Hub-owned action. | `main.go`, `hub.Service.Approve` | | `GET /health` | Liveness check. No authentication. | `main.go`, `hub.Service.Health` | The inbound API is frozen. See `docs/hub-api.md`. ## The Five Steps in Code | Step | Package | Notes | |---|---|---| | Hear | `hear` | Decode JSON, validate the frozen shape, make a request id. | | Understand | `understand` | The never-route check runs first, with no LLM. Then the OmniRoute LLM picks route, fanout, clarify, or no_match. | | Check | `check` | One identity (Sam) and a source that matches the token. | | Route | `route` | Dispatch. The action call holds no LLM. | | Answer | `answer` | Choose the reply shape from `source` and `want`. House TTS is out of band. | ## Primary Dependencies - HTTP server and client (Go 1.25, standard library `net/http`). - No third-party module. The binary is static and small. - OmniRoute, Home Assistant, MQTT, and Paperclip are called over HTTP. ## Destinations Each destination gets one client under `src/destinations/`. The client calls the destination API. The client does not hold business logic. ## Tests ```bash # Unit and round-trip tests. No network, no secrets. docker run --rm -v "$PWD/src":/src -w /src golang:1.25-alpine go test ./... ``` The fake `/ask` project (`src/tests/fakeproject/`) proves the Hub-to-project round trip. It has no real data and changes no state. ## Source Control - Gitea: `sam/central_ai_llm_master` - Local: `/home/sam/paseo/projects/central_ai_llm_master/`