commit b3658132dd7d9368119d688c05f0b35714ef15cc Author: Sam Rolfe Date: Sat Oct 10 14:44:54 2026 +1100 Initial Central AI Hub docs: brief, rules, README, outline context, architecture diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..a82649d --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +.env +*.visual-check.* diff --git a/AGENTS.md b/AGENTS.md new file mode 100644 index 0000000..372f510 --- /dev/null +++ b/AGENTS.md @@ -0,0 +1,91 @@ +# Central AI Hub (`central_ai_llm_master`) + +## Mission + +Build the **Hub**. The Hub is one small service. Every way in reaches every +ability through it. Build the ability once. All ways in get it. + +## Authority + +Read `hub_brief.md` in this folder first. It is the agreed design. If this file +and the brief disagree, the brief wins. + +- `hub_brief.md` — the agreed brief (source of truth). +- `README.md` — technical readme. +- `docs/outline/` — AI context. Start with `00-index.md`. + +## What the Hub does + +Five steps, in order: + +1. **Hear** — take voice or text from any way in. +2. **Understand** — the LLM works out what was asked. +3. **Check** — is this person allowed to ask for this? +4. **Route** — send it to the right destination. +5. **Answer** — return a short reply in the right shape for the device. + +The reply can be text, spoken audio (TTS), Artemis commands, a notification, an +email, or a mix. TTS can play on the house speakers or on the phone. + +## The dividing line + +> Does this need a decision, or does it need to happen? + +- **Happen** — fast and certain. Go straight to the destination. No LLM in the + path of the action. +- **Decision** — slow, multi-step, worth recording. Send to Paperclip. + +**Paperclip is the work bench, not the switchboard.** + +## Rules + +1. All models go through **OmniRoute**. Never call a provider directly. +2. All secrets come from **`environment.d`**. Never hard-code. +3. Own service, own port, own folder. +4. No LLM in the path of a fast or consequential action. +5. Paperclip only for slow, multi-step, recorded work. +6. Replies return to the source and stay short. +7. Restricted actions need **tap-to-approve** on the admin app. +8. Only the admin app changes parental controls. +9. A new ability registers with the Hub. Build it once. + +## Build order + +1. **Thin slice, end to end.** Issue a Paperclip API key. File one job from a + script. Get the result announced back. Prove the round trip. +2. **Hub skeleton.** Hear → understand → route → answer, with one destination. +3. **Approval flow.** "Did you ask for this?" on the admin app. +4. **Internet control.** Standalone service with a plain API. Device-side + enforcement. Admin-only. +5. **Artemis.** Standalone service with a plain API. Screen control only. +6. **Move Jervis's tools** into the Hub. Jervis becomes voice-only. +7. **Phone Kotlin app.** Wake word, voice to the Hub, replies and approvals. +8. **Email and school pipelines.** Stay independent. Connect when ready. + +## Definition of done (phase 1) + +- A Paperclip API key exists. +- One job is filed by script and its result is spoken. +- The round trip is recorded in `docs/outline/04-agent-runbook.md`. + +## How this project relates to the other projects + +This project owns the **shared Hub**. It does not own the destinations. + +| Project | Relation | +|---|---| +| Email agent | Own pipeline. Reports through the Hub when ready. | +| Compass / NHS | Own pipeline. Reports through the Hub when ready. | +| Internet use control | Destination. Exposes a plain API. The Hub calls it. | +| Artemis | Destination. Exposes a plain API. The Hub calls it. | +| Jervis | Becomes voice-only. Its tools move here. | +| dsh | Calls the Hub for actions. | + +Each project writes its own docs. Do not copy theirs here. Link to them. + +## Do not + +- Do not build one central brain. No single personality or memory. +- Do not put Paperclip in the path of a fast command. +- Do not duplicate a destination inside the Hub. +- Do not add a spoken keycode as the only lock for restricted actions. diff --git a/README.md b/README.md new file mode 100644 index 0000000..6310291 --- /dev/null +++ b/README.md @@ -0,0 +1,81 @@ +# Central AI Hub + +One small service that every way in reaches every ability through. Built once, +shared by the phone app, the house voice, chat, and the admin app. + +## Demonstrated Skills & Tech Stack + +- **Core Technologies**: Go or Python service · HTTP JSON API · MQTT · LLM + intent routing · OmniRoute gateway · Docker +- **Key Tools**: Jervis (voice) · Home Assistant · Paperclip · Artemis · + internet use control · Apprise / NTFY · OmniRoute +- **Engineering Capabilities**: service design · intent routing · authorization + and approval flows · event-driven integration · deterministic safety for + high-consequence actions + +## Quick Start + +```bash +# Phase 1 — prove the Paperclip round trip +# 1. Create an agent API key in Paperclip. +# 2. Export it for the test only. +export PAPERCLIP_API_KEY= +# 3. File one job. +curl -s -X POST http://192.168.20.13:3100/api/issues \ + -H "Authorization: Bearer $PAPERCLIP_API_KEY" \ + -H "Content-Type: application/json" \ + -d '{"title":"round-trip test","description":"prove the return path"}' +``` + +Full steps: `docs/outline/04-agent-runbook.md`. + +## System Architecture + +```mermaid +flowchart LR + subgraph IN["Ways in"] + PHONE["Phone app
wake word + voice"] + ADMIN["Admin app
restricted actions"] + ESP["ESP32 voice
Hey Jervis"] + DSH["dsh chat"] + CONSOLE["Console portal"] + end + + HUB{{"HUB
hear - understand - check - route - answer"}} + + subgraph OUT["Destinations"] + HA["Home Assistant"] + SPK["Speakers
Jervis TTS"] + NET["Internet control"] + ART["Artemis
phone screen"] + PC["Paperclip
slow jobs"] + WEB["Web search"] + APP["Apprise / NTFY"] + end + + PHONE --> HUB + ESP --> HUB + DSH --> HUB + CONSOLE --> HUB + ADMIN --> HUB + HUB --> HA + HUB --> SPK + HUB --> NET + HUB --> ART + HUB --> PC + HUB --> WEB + HUB --> APP + PC -. result .-> HUB +``` + +*Interactive architecture map:* [maps.lab.audasmedia.com.au/central_ai_llm_master](https://maps.lab.audasmedia.com.au/central_ai_llm_master/docs/) + +## Usage & Configuration + +- **Model calls** go through OmniRoute at `http://192.168.20.13:20129/v1`. +- **Secrets** come from `~/.config/environment.d/10-secrets.conf`. +- **Paperclip** is at `http://192.168.20.13:3100`. An API key is required. +- **Home Assistant** is at `http://192.168.20.30:8123`. +- **Jervis** (voice) is at `http://192.168.20.13:8501`. + +The design brief is `hub_brief.md`. Project instructions are `AGENTS.md`. diff --git a/docs/archify/hub.architecture.json b/docs/archify/hub.architecture.json new file mode 100644 index 0000000..ad658a3 --- /dev/null +++ b/docs/archify/hub.architecture.json @@ -0,0 +1,61 @@ +{ + "schema_version": 1, + "diagram_type": "architecture", + "meta": { + "title": "Central AI Hub", + "output": "docs/hub-architecture-map.html", + "quality_profile": "showcase", + "views": [ + { + "id": "fast-command", + "label": "Fast command", + "focus": ["esp32", "hub", "ha", "spk"], + "note": "A fast command goes straight to the destination. No LLM waits in the action path." + }, + { + "id": "slow-job", + "label": "Slow job", + "focus": ["phone", "hub", "pc"], + "note": "A slow job goes to Paperclip. The result returns to the Hub later." + }, + { + "id": "restricted", + "label": "Restricted action", + "focus": ["admin", "hub", "net"], + "note": "Only the admin app can change parental controls. Voice may ask; the app confirms." + } + ] + }, + "components": [ + { "id": "phone", "type": "frontend", "label": "Phone app", "sublabel": "wake word + voice", "pos": [40, 80], "size": [150, 64] }, + { "id": "admin", "type": "security", "label": "Admin app", "sublabel": "restricted actions", "pos": [40, 200], "size": [150, 64] }, + { "id": "esp32", "type": "external", "label": "ESP32 voice", "sublabel": "Hey Jervis", "pos": [40, 320], "size": [150, 64] }, + { "id": "dsh", "type": "frontend", "label": "dsh chat", "sublabel": "per person", "pos": [40, 440], "size": [150, 64] }, + { "id": "hub", "type": "backend", "label": "Hub", "sublabel": "hear - understand - check - route - answer", "pos": [390, 260], "size": [190, 80], "tag": "one shared service" }, + { "id": "ha", "type": "external", "label": "Home Assistant", "sublabel": "devices, timers", "pos": [790, 40], "size": [160, 64] }, + { "id": "spk", "type": "external", "label": "Speakers", "sublabel": "Jervis TTS", "pos": [790, 150], "size": [160, 64] }, + { "id": "net", "type": "backend", "label": "Internet control", "sublabel": "parental limits", "pos": [790, 260], "size": [160, 64] }, + { "id": "art", "type": "backend", "label": "Artemis", "sublabel": "phone screen", "pos": [790, 370], "size": [160, 64] }, + { "id": "pc", "type": "backend", "label": "Paperclip", "sublabel": "slow jobs", "pos": [790, 480], "size": [160, 64] }, + { "id": "web", "type": "cloud", "label": "Web search", "sublabel": "Tavily", "pos": [790, 590], "size": [160, 64] }, + { "id": "app", "type": "backend", "label": "Apprise / NTFY", "sublabel": "notify + email", "pos": [790, 700], "size": [160, 64] } + ], + "boundaries": [ + { "kind": "region", "label": "Ways in", "wraps": ["phone", "admin", "esp32", "dsh"], "pad": 26 }, + { "kind": "region", "label": "Destinations", "wraps": ["ha", "spk", "net", "art", "pc", "web", "app"], "pad": 26 } + ], + "connections": [ + { "id": "phone-in", "from": "phone", "to": "hub", "label": "voice or text" }, + { "id": "admin-in", "from": "admin", "to": "hub", "label": "restricted" }, + { "id": "esp-in", "from": "esp32", "to": "hub", "label": "command" }, + { "id": "dsh-in", "from": "dsh", "to": "hub", "label": "action request" }, + { "id": "to-ha", "from": "hub", "to": "ha", "label": "do it" }, + { "id": "to-spk", "from": "hub", "to": "spk", "label": "speak" }, + { "id": "to-net", "from": "hub", "to": "net", "label": "confirm" }, + { "id": "to-art", "from": "hub", "to": "art", "label": "screen control" }, + { "id": "to-pc", "from": "hub", "to": "pc", "label": "file job" }, + { "id": "to-web", "from": "hub", "to": "web", "label": "search" }, + { "id": "to-app", "from": "hub", "to": "app", "label": "notify" }, + { "id": "pc-back", "from": "pc", "to": "hub", "label": "result", "variant": "dashed" } + ] +} diff --git a/docs/diagrams/hub-architecture.png b/docs/diagrams/hub-architecture.png new file mode 100644 index 0000000..6d314bb Binary files /dev/null and b/docs/diagrams/hub-architecture.png differ diff --git a/docs/hub-architecture-map.html b/docs/hub-architecture-map.html new file mode 100644 index 0000000..bef0f8d --- /dev/null +++ b/docs/hub-architecture-map.html @@ -0,0 +1,13716 @@ + + + + + + + Central AI Hub Diagram + + + + + + + + + + + +
+ +
+
+
+

Central AI Hub

+
+
+ + + + + + +
+ + Central AI Hub + A architecture diagram generated by Archify. + + + + + + + + + + + + + + + + + + + + + + + + + Ways in + + + Destinations + + + + + + + + + + + + + + + + + + Phone app · wake word + voice · Ways in + + + + Phone app + wake word + voice + + + + Admin app · restricted actions · Ways in + + + + Admin app + restricted actions + + + + ESP32 voice · Hey Jervis · Ways in + + + + ESP32 voice + Hey Jervis + + + + dsh chat · per person · Ways in + + + + dsh chat + per person + + + + Hub · hear - understand - check - route - answer · Architecture component · one shared service + + + + Hub + hear - understand - check - route - answer + one shared service + + + + Home Assistant · devices, timers · Destinations + + + + Home Assistant + devices, timers + + + + Speakers · Jervis TTS · Destinations + + + + Speakers + Jervis TTS + + + + Internet control · parental limits · Destinations + + + + Internet control + parental limits + + + + Artemis · phone screen · Destinations + + + + Artemis + phone screen + + + + Paperclip · slow jobs · Destinations + + + + Paperclip + slow jobs + + + + Web search · Tavily · Destinations + + + + Web search + Tavily + + + + Apprise / NTFY · notify + email · Destinations + + + + Apprise / NTFY + notify + email + + + + + + voice or text + + + + restricted + + + + command + + + + action request + + + + do it + + + + speak + + + + confirm + + + + screen control + + + + file job + + + + search + + + + notify + + + + result + + + + + Legend + + + Frontend + + + + Backend + + + + Cloud + + + + Security + + + + External + + + +

+ + + + + + + + +
+ + +
+ +
+ +
+ + + + diff --git a/docs/hub-architecture.mmd b/docs/hub-architecture.mmd new file mode 100644 index 0000000..7dfc659 --- /dev/null +++ b/docs/hub-architecture.mmd @@ -0,0 +1,36 @@ +flowchart LR + subgraph IN["Ways in"] + PHONE["Phone app
wake word + voice"] + ADMIN["Admin app
restricted actions"] + ESP["ESP32 voice
Hey Jervis"] + DSH["dsh chat"] + CONSOLE["Console portal"] + end + + HUB{{"HUB
hear - understand - check - route - answer"}} + + subgraph OUT["Destinations"] + HA["Home Assistant"] + SPK["Speakers
Jervis TTS"] + NET["Internet control"] + ART["Artemis
phone screen"] + PC["Paperclip
slow jobs"] + WEB["Web search"] + APP["Apprise / NTFY"] + end + + PHONE --> HUB + ESP --> HUB + DSH --> HUB + CONSOLE --> HUB + ADMIN --> HUB + HUB --> HA + HUB --> SPK + HUB --> NET + HUB --> ART + HUB --> PC + HUB --> WEB + HUB --> APP + PC -. result .-> HUB + + click HUB "https://maps.lab.audasmedia.com.au/central_ai_llm_master/docs/" "View Archify Map" diff --git a/docs/outline/00-index.md b/docs/outline/00-index.md new file mode 100644 index 0000000..4d0748f --- /dev/null +++ b/docs/outline/00-index.md @@ -0,0 +1,38 @@ +# Central AI Hub — AI Document Index + +> **Target**: AI Agents +> **Writing Style**: ASD-STE100 Simplified Technical English (`ste-writing`). + +## Document Catalog (Inject Specific Document) + +Read this index to inject the exact file you need. Do not search all files. + +| Document Title | Path | Scope / Description | +| :--- | :--- | :--- | +| **System Overview** | `docs/outline/01-system-overview.md` | Explains the Hub purpose, its five steps, and the destinations. | +| **Configuration & Env** | `docs/outline/02-config-and-env.md` | Lists services, ports, env vars, and secret paths. | +| **Code Structure Map** | `docs/outline/03-code-map.md` | Shows the planned folder layout and entry points. | +| **AI Agent Runbook** | `docs/outline/04-agent-runbook.md` | Gives steps to build, test, and restart Hub work. | +| **Design Brief** | `hub_brief.md` | The agreed design. This file is the source of truth. | +| **Project Rules** | `AGENTS.md` | Mission, rules, build order, and project relations. | + +--- + +## System Summary + +The Hub is one service. Every way in reaches every ability through it. The Hub +does five steps: hear, understand, check, route, and answer. The Hub does not +hold a personality or a memory. The Hub does not do the destination work. + +## Core Configuration + +- **Env File**: `~/.config/environment.d/10-secrets.conf` +- **Config Directory**: `docs/` +- **Active Ports**: Hub port not allocated yet. + +## Agent Restart Steps + +1. Read the Document Catalog above. Inject only required files. +2. Read `hub_brief.md`. +3. Check git status: `git status`. +4. Check recent commits: `git log -n 5 --oneline`. diff --git a/docs/outline/01-system-overview.md b/docs/outline/01-system-overview.md new file mode 100644 index 0000000..4743531 --- /dev/null +++ b/docs/outline/01-system-overview.md @@ -0,0 +1,59 @@ +# Central AI Hub — System Overview + +> **Writing Style**: ASD-STE100 Simplified Technical English (`ste-writing`). + +## Purpose + +The Hub is one service. Every way in reaches every ability through the Hub. Build +each ability once. All ways in get it. + +Today, Jervis (voice) and dsh (chat) each understand the user and act. A third +way in, the phone app, would repeat the same work. The Hub stops this repeat. + +## The Five Steps + +1. **Hear** — take voice or text from any way in. +2. **Understand** — the LLM works out what the user asked. +3. **Check** — test whether the user may ask for this. +4. **Route** — send the request to one destination. +5. **Answer** — return a short reply in the right shape. + +## Ways In + +- Phone app (Kotlin) — wake word, voice, controls. +- Admin app (Kotlin) — restricted actions only. +- ESP32 voice — "Hey Jervis". +- dsh chat — per-person chat. +- Console portal — web dashboard. + +## Destinations + +| Destination | Job | +|---|---| +| Home Assistant | Lights, switches, timers, calendar. | +| Speakers (Jervis) | Speak and announce. | +| Internet control | Parental limits on kids' devices. | +| Artemis | Operate the phone screen. | +| Paperclip | Slow, multi-step, recorded work. | +| Web search | Tavily search. | +| Apprise / NTFY | Notifications and email. | + +## Reply Shapes + +The Hub returns one reply. The reply can hold text, spoken audio (TTS), Artemis +commands, a notification, or an email. TTS can play on the house speakers or on +the phone. The Hub returns the reply to the source. + +## The Dividing Line + +The Hub asks one question: does this need a decision, or does it need to happen? + +- **Happen** — fast and certain. Go straight to the destination. No LLM in the + path of the action. +- **Decision** — slow, multi-step, worth recording. Send to Paperclip. + +## What the Hub Is Not + +- Not a central brain. No single personality or memory. +- Not Paperclip. The Hub does not wait minutes for an answer. +- Not a destination. The Hub does not turn off the internet itself. diff --git a/docs/outline/02-config-and-env.md b/docs/outline/02-config-and-env.md new file mode 100644 index 0000000..f792cd7 --- /dev/null +++ b/docs/outline/02-config-and-env.md @@ -0,0 +1,43 @@ +# Central AI Hub — Configuration & Environment + +> **Writing Style**: ASD-STE100 Simplified Technical English (`ste-writing`). + +## Secrets + +All secrets come from `~/.config/environment.d/10-secrets.conf` on each machine. +Never hard-code a secret. Never commit a secret. + +Relevant keys: + +| Key | Use | +|---|---| +| `OMNIROUTE_API_KEY` | Model calls through OmniRoute. | +| `PAPERCLIP_API_KEY` | File jobs to Paperclip. Does not exist yet. | +| `TAVILY_API_KEY` | Web search. | +| `OL_API_KEY` | Outline docs. | +| `VIKUNJA_TOKEN` | Vikunja tasks. | +| `GITEA_TOKEN` | Gitea repository. | + +## Services and Ports + +| Service | Host | Port | Use | +|---|---|---|---| +| OmniRoute | 192.168.20.13 | 20129 | Model gateway. | +| Paperclip | 192.168.20.13 | 3100 | Job orchestration. | +| Jervis (voice) | 192.168.20.13 | 8501 | Speak and announce. | +| Home Assistant | 192.168.20.30 | 8123 | Devices and timers. | +| MQTT | 192.168.20.13 | 1883 | Voice topics. | +| Apprise | 192.168.20.35 | 8210 | Notifications. | +| Hub | not allocated | — | This service. | + +## Config Paths + +- Brief: `hub_brief.md` +- Rules: `AGENTS.md` +- Docs: `docs/` +- Outline context: `docs/outline/` + +## Rule + +A new project gets its own service, its own port, and its own folder. Do not +merge a destination into the Hub. diff --git a/docs/outline/03-code-map.md b/docs/outline/03-code-map.md new file mode 100644 index 0000000..de94862 --- /dev/null +++ b/docs/outline/03-code-map.md @@ -0,0 +1,56 @@ +# Central AI Hub — Code Structure Map + +> **Writing Style**: ASD-STE100 Simplified Technical English (`ste-writing`). +> **Status**: Planned. The Hub is not built yet. + +## Planned 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 + docs/ + hub-architecture.mmd Mermaid source + hub-architecture-map.html Archify map + diagrams/ rendered images + archify/ Archify JSON input + outline/ AI context documents + vikunja-tasks.json human task list + src/ Hub service code (to build) + main.* HTTP entry point + hear/ takes voice or text + understand/ LLM intent routing + check/ authorization and approval + route/ dispatch to a destination + answer/ reply shaping (text, TTS, notify) + destinations/ one client per destination + tests/ unit and round-trip tests +``` + +## Entry Points + +| Entry point | Use | +|---|---| +| `POST /ask` | Send a voice transcript or text. Returns a reply. | +| `POST /approve` | Admin app confirms a restricted action. | +| `GET /health` | Liveness check. | + +The API contract is not final. See `hub_brief.md`. + +## Primary Dependencies + +- HTTP server (Go or Python — decide before build). +- HTTP client for OmniRoute, Home Assistant, Paperclip. +- MQTT client for voice topics. +- Tavily API client for web search. + +## Destinations + +Each destination gets one client under `src/destinations/`. The client calls the +destination API. The client does not hold business logic. + +## Source Control + +- Gitea: `sam/central_ai_llm_master` +- Local: `/home/sam/paseo/projects/central_ai_llm_master/` diff --git a/docs/outline/04-agent-runbook.md b/docs/outline/04-agent-runbook.md new file mode 100644 index 0000000..42717cc --- /dev/null +++ b/docs/outline/04-agent-runbook.md @@ -0,0 +1,55 @@ +# Central AI Hub — AI Agent Runbook + +> **Writing Style**: ASD-STE100 Simplified Technical English (`ste-writing`). + +## Phase 1 — Prove the Paperclip Round Trip + +This phase has no Hub code. It proves the missing link: a job that leaves and a +result that returns. + +### Steps + +1. Create a Paperclip agent API key for this project. + - Paperclip board: `http://192.168.20.13:3100`. + - Store the key in `~/.config/environment.d/10-secrets.conf` as + `PAPERCLIP_API_KEY`. Never commit it. +2. File one job with `curl`. Use the issue-create endpoint. +3. Confirm the job appears in the Paperclip board. +4. Wait for the agent to close the job. +5. Send the result to Jervis `POST /announce` so the house speaks it. +6. Record the result in this file. + +### Commands + +```bash +export PAPERCLIP_API_KEY= +curl -s -X POST http://192.168.20.13:3100/api/issues \ + -H "Authorization: Bearer $PAPERCLIP_API_KEY" \ + -H "Content-Type: application/json" \ + -d '{"title":"round-trip test","description":"prove the return path"}' + +# Speak the result. +curl -s -X POST http://192.168.20.13:8501/announce \ + -H "Content-Type: application/json" \ + -d '{"text":"Round trip works."}' +``` + +### Definition of Done + +- The job appears in Paperclip. +- The job closes. +- The house speaks the result. +- This file records the result. + +## After Phase 1 + +Follow the build order in `AGENTS.md`. Do not start a destination before the +round trip works. + +## Health Checks + +```bash +curl -s http://192.168.20.13:3100/health # Paperclip +curl -s http://192.168.20.13:8501/health # Jervis +curl -s -o /dev/null -w '%{http_code}\n' http://192.168.20.30:8123/ # HA +``` diff --git a/docs/vikunja-tasks.json b/docs/vikunja-tasks.json new file mode 100644 index 0000000..5432a19 --- /dev/null +++ b/docs/vikunja-tasks.json @@ -0,0 +1,16 @@ +{ + "title": "Central AI Hub - Human Task Overview", + "description": "High-level task checklist for human team members.", + "tasks": [ + { "title": "Create Paperclip agent API key and store in secrets", "done": false }, + { "title": "Prove the Paperclip round trip (file job, speak result)", "done": false }, + { "title": "Decide the Hub language and port", "done": false }, + { "title": "Build the Hub skeleton (hear, understand, route, answer)", "done": false }, + { "title": "Add the tap-to-approve flow on the admin app", "done": false }, + { "title": "Build the internet control destination service", "done": false }, + { "title": "Build the Artemis destination service", "done": false }, + { "title": "Move Jervis action tools into the Hub", "done": false }, + { "title": "Build the phone Kotlin app", "done": false }, + { "title": "Connect the email and school pipelines", "done": false } + ] +} diff --git a/hub_brief.md b/hub_brief.md new file mode 100644 index 0000000..f737789 --- /dev/null +++ b/hub_brief.md @@ -0,0 +1,150 @@ +# The Hub — a short brief + +**Purpose:** tell every project where it fits and the rules it must follow. +**Written:** 2026-10-10 +**Status:** agreed direction, not a build order. + +--- + +## The idea in one line + +**Share the plumbing. Keep the brains separate. Put one small hub in the middle.** + +Every way in (phone, house voice, chat) reaches every ability (lights, internet, +Artemis, Paperclip) through one place — built once, not repeated. + +--- + +## What already works (do not rebuild) + +| System | What it is | +|---|---| +| **Jervis** | The house voice. ESP32 "Hey Jervis" → STT → agent → TTS → speakers. Controls HA, timers, reminders, shopping, calendar, music, weather, web search, family messages. | +| **dsh** | Per-person chat (sam / jo / harry / finn). Memory, images, video, documents. | +| **Console portal** | Logins and dashboard for the family. | +| **Front Door Cam** | Its own separate ESP32. Visitor detection, Gemini sees the person, voice asks them to speak. | +| **OmniRoute** | The model gateway. All models go through here. | +| **Home Assistant** | Devices, timers, calendar, notifications. | +| **Shared** | Apprise, Snapcast, STT/TTS, n8n, secrets in `environment.d`. | + +These stay. The hub is added, not a replacement. + +--- + +## What is new + +- The **Hub** (this brief). +- **Email agent** — its own pipeline. +- **School (Compass / Teams)** — its own pipeline. +- **Internet use control** — a destination the hub calls. +- **Artemis** — a destination the hub calls. +- **Kotlin phone app** — a new way in (wake word, voice, controls). +- **Admin app + kids app** — parental control, admin only. + +--- + +## What the Hub is + +One service that does five steps: + +1. **Hear** — takes voice or text from any way in. +2. **Understand** — the LLM works out what was asked. +3. **Check** — is this person allowed to ask for this? +4. **Route** — sends it to the right destination. +5. **Answer** — returns a short reply in the right shape for the device. + +The reply can be **text**, **spoken audio (TTS)**, **Artemis commands**, **a phone +notification**, **an email**, or a mix. TTS can play on the **house speakers** or +on the **phone**. + +### What the Hub is NOT + +- **Not a central brain.** It does not hold one personality or one memory. +- **Not Paperclip.** It never waits minutes for an answer. +- **Not a destination.** It does not turn off the internet itself. It sends the + request to the service that does. + +### The dividing line + +One question sorts every request: + +> **Does this need a decision, or does it need to happen?** + +- **Happen** (fast, certain) → straight to the destination: HA, internet control, + Artemis, speakers. No LLM in the path of the action. +- **Decision** (slow, multi-step, worth recording) → Paperclip. + +**Paperclip is the work bench, not the switchboard.** It is never in the path of +a fast or high-consequence command. + +--- + +## Where each system fits + +| System | Role | With the Hub | +|---|---|---| +| **Jervis** | House voice | Becomes the **voice** (speak / announce), not a list of tools. Its action tools move into the Hub over time. | +| **dsh** | Chat | Calls the Hub for actions instead of keeping its own copies. | +| **Console portal** | Login + dashboard | Unchanged. May show Hub status and approvals. | +| **Front Door Cam** | Visitor intercom | Stays separate. May use the Hub only to speak. | +| **Email agent** | Own pipeline (n8n) | Standalone. May report results through the Hub. | +| **School agent** | Own pipeline (n8n) | Standalone. May report results through the Hub. | +| **Internet control** | Destination | The Hub calls its API. Enforcement happens on the kids' devices. | +| **Artemis** | Destination | The Hub calls its API. Artemis touches the phone screen. | +| **Paperclip** | Work bench | The Hub files jobs and hears the answer back. | +| **Phone app** | Way in | Sends voice to the Hub. Shows replies, notifications, approvals. | + +--- + +## Rules every project follows + +1. **All models go through OmniRoute.** Never call a provider directly. +2. **All secrets come from `environment.d`.** Never hard-code. +3. **Own service, own port, own folder.** Do not merge into another project. +4. **No LLM in the path of a fast or consequential action.** Deterministic calls + for anything that turns something off. +5. **Paperclip only for slow, multi-step, recorded work.** Never make a person + wait on it. +6. **Replies return to the source, and stay short.** Speaker → one line. Phone → + notification. Chat → text. No long-winded answers. +7. **Restricted commands need tap-to-approve** on the admin app. This includes + parental controls and any job filed to Paperclip. +8. **Only the admin app can change parental controls.** Kids' apps and desktop + exes may only obey and report. +9. **New work registers with the Hub.** A capability is added once, and every way + in gets it. + +--- + +## Safety + +- **Voice is shared and unauthenticated.** Anyone in the house can speak. +- **The admin app is the only trusted door** for restricted actions. +- **A spoken keycode is not the lock.** It can be overheard and misheard. Voice + may *ask*; the admin app **confirms** with "Did you ask for this?". +- **Approval is required** for parental controls and Paperclip jobs. + +--- + +## Build order + +1. **Thin slice, end to end.** Issue a Paperclip API key, file one job from a + script, and get the result announced back. Proves the round trip. +2. **Hub skeleton.** Hear → understand → route → answer, with one destination + (HA or speakers) working. +3. **Approval flow.** "Did you ask for this?" on the admin app. +4. **Internet control.** Standalone service with a plain API. Device-side + enforcement. Admin-only. +5. **Artemis.** Standalone service with a plain API. Screen control only. +6. **Move Jervis's tools** into the Hub. Jervis becomes voice-only. +7. **Phone Kotlin app.** Wake word, voice to the Hub, replies and approvals. +8. **Email and school pipelines** stay independent and connect when ready. + +--- + +## What is still open + +- Exact API contract for a job (title, brief, project, agent). +- How Artemis receives voice (stream vs file) and when phone TTS is used. +- Which Paperclip company / projects to use. +- Identity: how the Hub knows which family member is speaking.