feat(personal): Sophia replaces Bourdain and Cousteau

Adds Sophia Petrillo (The Golden Girls) to the personal team and retires
Bourdain and Cousteau — a 2:1 merge, net -1 agent (10 -> 9 personal,
18 -> 17 total).

Why: the personal team casts fictional characters. Bourdain and Cousteau
are real people, one with significant baggage and one who died by suicide,
and neither had a dedicated MCP server or capability. Sophia is fictional,
plausibly owns both domains (an Italian grandmother knows food; tending
plants and the tank is housekeeping), and is the first personal agent to
actuate the house via the new Hecate MCP server.

Graph: Sophia inherits all 11 node types unchanged (Recipe, Restaurant,
Ingredient, Meal, Technique + Species, Plant, Tank, Garden, Ecosystem,
Observation). Uniqueness constraints are keyed on node label, not agent,
so there is no schema or data migration. Historical Note tags
(from:bourdain, to:cousteau) are deliberately left intact as an accurate
record. Schema bumped to 2.5.0.

Also:
- New docs/tools/hecate.md + prompts/tools/hecate.md, documenting the
  physical-actuation discipline (never guess a room or device slug) and
  stating plainly what Hecate cannot do yet: no sensor readings (Demeter
  is REST-only), no weather, and set_timer is routine-bound with no
  cancel — the conversational timer is coming to Daedalus.
- Shawn gains Periplus in the docs. The server was already wired in
  iolaus but never described in any prompt, so the model was handed a
  tool it was never told about — including the never-estimate-coordinates
  rule.
- Corrected stale counts (15/16/18 assistants -> 17) and the stale
  "Bowie's Domain" schema heading missed when David replaced Bowie.
- Removed utils/neo4j-schema-init.py.bak, a pre-Watson artifact.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-07-26 19:24:16 -04:00
parent 22074206db
commit db59266527
44 changed files with 1027 additions and 1867 deletions

View File

@@ -44,7 +44,7 @@ The canonical flow:
- **Ann** — primary user. Website authoring (FlexPages), blog post creation, content calendar execution, event page creation. The website is Ann's primary marketing surface; Angelia is how the website gets touched.
Other agents may eventually use Angelia (e.g., Cousteau if a "garden notes" section gets added), but Ann is the only current user.
Other agents may eventually use Angelia (e.g., Sophia if a "garden notes" section gets added), but Ann is the only current user.
## What It's Good For

134
docs/tools/hecate.md Normal file
View File

@@ -0,0 +1,134 @@
# Hecate
> The house — lights, the receiver, IR devices, and saved routines. The MCP server is the actuator layer; the agent is the brain.
- **MCP server name:** `hecate`
- **Prompt snippet:** [prompts/tools/hecate.md](../../prompts/tools/hecate.md)
## What It Is
[Hecate](https://git.helu.ca/r/hecate) is the estate's voice-first home-automation controller — a FastAPI + FastMCP service that owns the device registry and drives the physical devices in Robert's home: Tuya/SmartLife bulbs and outlets, HomeKit wall plugs (via the Propolos bridge, no vendor cloud), the Onkyo AV receiver over eISCP, and Broadlink IR blasters for TVs, soundbars, projectors, and legacy air conditioning. Named for the Greek goddess of the household threshold and the crossroads.
Hecate deliberately contains no AI. It exposes tools; an agent decides what to call. It is the only MCP server on the personal team that changes physical state in the house — every other tool reads, writes text, or searches.
**Two stores, as with Kairos and Periplus.** Hecate holds the **canonical live state** — which devices exist, what room they're in, whether the light is currently on, what the receiver's volume is. Neo4j holds the **interpretation** — that the reef tank in the living room matters, that this plant has been struggling since June. Hecate knows the lamp is on; it has no idea why anyone cares. When Sophia records that the aquarium heater failed, the *event* goes in Neo4j as an `Observation`; the *device* stays Hecate's.
## ⚠️ Critical Discipline: Never Guess a Device or Room
The device registry lives in Hecate's database and is **per-install**. Room ids (`living_room`) and device ids (`lr_main`, `lr_fan_plug`) are human-authored slugs that exist only in that database. There is no fixed list, and none of them are guessable from conversation.
Acting on a guessed slug either errors or — worse — actuates the wrong thing. Unlike a bad search result, this has physical consequences: the light someone is reading by goes out, the receiver powers down mid-film.
The rules, which have no exceptions:
1. **Call `list_rooms` / `list_devices` before acting.** Every session. The registry is not to be memorised across conversations — devices get added, renamed, and disabled.
2. **If there's no obvious match for what the user said, ask.** Do not pick the closest-sounding slug.
3. **Confirm before disruptive actions** — whole-house changes (`room=""`), powering off a receiver that's in use, running a multi-room routine.
4. **Name the device when reporting failure.** "Can't reach the patio blaster — it's offline" beats "command failed." Hecate's own error strings do this; preserve it.
## MCP Tools
### Registry — always start here
| Tool | Purpose |
|---|---|
| `list_rooms()` | Every room with its device count. The room-slug source of truth. |
| `list_devices(room="")` | Every registered device with type, platform, and room. Optionally scoped to one room. |
### Lights and power
| Tool | Purpose |
|---|---|
| `lights_on(room="", brightness=-1)` | Turn lights on. `brightness` 0100; `-1` leaves it unchanged (and is ignored by outlets). `room=""` is the whole house. |
| `lights_off(room="")` | Turn lights off, optionally scoped to a room. |
| `lights_color(color, room="")` | Set colour. **RGB bulbs only** — white/dimmer bulbs and outlets are unaffected. Named colours: red, orange, yellow, green, cyan, blue, purple, magenta, pink, white, warmwhite, coolwhite. |
| `device_power(device_id, state)` | One specific device by id. `state` is `"on"` or `"off"`. This is how you address a single plug when the room-scoped tools are too broad. |
### Onkyo receiver
| Tool | Purpose |
|---|---|
| `receiver_power(state)` | On or off. |
| `set_volume(level)` | Main-zone volume, 0100. |
| `set_input(source)` | Select an input, by eISCP name or friendly label. |
| `get_receiver_status()` | Current power, volume, and input. |
### IR, routines, timing
| Tool | Purpose |
|---|---|
| `ir_command(device_id, command)` | Fire a learned IR command through the target's blaster. Valid commands come from that device's learned command map — they are per-device, not a fixed vocabulary. |
| `run_routine(routine_id)` | Execute a saved routine's steps in order; returns per-step outcomes. Steps are best-effort — one failure doesn't abort the rest. |
| `list_routines()` | All routines with id, name, enabled state, trigger, and step count. |
| `set_timer(routine_id, minutes=0, seconds=0, label="")` | Fire an **existing routine** after a delay. See the gotcha below — this is not a kitchen timer. |
| `list_timers(status="")` | List timers, optionally filtered (`pending`, `fired`, `cancelled`). |
| `wait(seconds=0, minutes=0)` | Pause inside a routine before the next step. |
### Wallboard (Phase 2)
`list_wallboards`, `create_wallboard`, `get_wallboard`, `get_wallboard_version`, `get_wallboard_catalog`, `put_wallboard_version`, `activate_wallboard_version`, `comfy_generate`, `gallery_search` — the push-model kiosk display: an agent authors a full HTML board and pushes it. Not part of Sophia's day-to-day; see [hecate/docs/wallboard.md](https://git.helu.ca/r/hecate/src/branch/main/docs/wallboard.md).
## Canonical Workflows
### Turning something on
```
list_rooms() # or list_devices() if the user named a device
→ match what the user said to a real slug
→ lights_on(room="living_room", brightness=60)
```
Step 1 is non-negotiable. If the match is ambiguous, ask rather than guess.
### Addressing one device rather than a room
```
list_devices(room="living_room") # find the specific plug
→ device_power(device_id="lr_fan_plug", state="on")
```
Room-scoped `lights_*` tools hit every light-like device in the room. For "turn on the fan plug," use `device_power`.
### Running a saved sequence
```
list_routines() # routine ids are slugs: "movie_time", "goodnight"
→ run_routine(routine_id="movie_time")
```
Read the per-step outcomes in the response — a routine reports partial failure rather than throwing.
## Who Uses Hecate
- **Sophia** — primary and effectively sole user. The house is her domain; she is the only personal agent wired to it.
- No other agent has Hecate in its server list. If a request from another agent needs the house, it routes to Sophia by message.
External non-agent clients (the Theia kiosk, a scheduled wallboard prompt) connect with their own PATs — out of scope here.
## What It's Good For
- Actuating lights, plugs, the receiver, and IR devices by room or by device
- Discovering what the house actually contains, live
- Running saved multi-step routines ("movie time", "goodnight")
- Authoring and serving the wallboard kiosk display
## What It's Not Good For
- **Reading any sensor.** See the gotchas — nothing is exposed.
- **Weather.** Not exposed as a tool yet.
- **Conversational timers and reminders.** Not what `set_timer` is.
- Remembering *why* something matters — that's Neo4j's job.
- Scheduling in the human sense — cron/sun triggers are configured in Hecate's own UI; the household calendar is Kairos (Shawn).
## Known Gotchas
- **Never guess a room or device slug.** See the Critical Discipline section — this is the failure mode with physical consequences.
- **No sensor readings are exposed via MCP.** Hecate integrates **Demeter**, the estate's plant/aquarium sensor server (soil moisture, temperature), and sensor-capable Broadlink blasters report temperature/humidity — but all of it is reachable only over REST and Prometheus. There is **no MCP tool** for any reading. An agent cannot see soil moisture, water temperature, or room temperature. *On the Hecate backlog.* Until then the agent asks the user and records an `Observation` in Neo4j.
- **No weather or forecast tool.** A weather data source exists inside Hecate for the wallboard (`sources/weather.py`, Open-Meteo) but is not exposed via MCP. *Also on the Hecate backlog.*
- **`set_timer` is not a kitchen timer.** It requires a **pre-existing `routine_id`** and fires that routine after a delay — there is no tool to create a routine, and **no cancel-timer tool** (cancellation is REST-only). "Set a 10-minute timer" is not expressible. The conversational timer/reminder capability is planned for **Daedalus**, not Hecate. An agent must not imply it is holding a timer.
- **`lights_color` only affects RGB bulbs.** White bulbs, dimmers, and outlets in the same room are silently unaffected — that's not a failure, but say so rather than claiming the room changed colour.
- **`brightness=-1` means "don't change it."** Passing `0` is a real value and will dim the light to nothing.
- **`room=""` is the whole house.** Easy to trigger accidentally by omitting the argument.
- **Timers survive restarts; cron occurrences do not.** Past-due timers fire on startup; a 7 AM schedule missed during an outage is *not* replayed at 2 PM. Deliberate.
- **Auth is owner-only.** The `/mcp` mount sits behind an ASGI guard — a valid non-owner credential gets **403**, not 401. Agents authenticate with an owner-scoped PAT (`hecate_pat_…`) as a static bearer header; Pallas does not forward inbound auth downstream.
- **The server sends its own instructions.** Hecate's FastMCP server ships `_SERVER_INSTRUCTIONS` describing room/device resolution to every client automatically. Don't duplicate that guidance verbatim in an agent prompt — add only what it doesn't say.

View File

@@ -1,6 +1,6 @@
# Neo4j Knowledge Graph — Engineering Team
You have access to a unified Neo4j knowledge graph shared across fifteen AI assistants (9 personal, 4 work, 2 engineering).
You have access to a unified Neo4j knowledge graph shared across seventeen AI assistants (9 personal, 5 work, 3 engineering).
## Principles

View File

@@ -1,6 +1,6 @@
# Neo4j Knowledge Graph — Personal Team
You have access to a unified Neo4j knowledge graph shared across all assistants (10 personal, 5 work, 3 engineering).
You have access to a unified Neo4j knowledge graph shared across all assistants (9 personal, 5 work, 3 engineering).
## Principles
@@ -36,9 +36,8 @@ MERGE (a)-[:RELATIONSHIP]->(b)
| **Hypatia** | Learning & Reading | Book, Author, LearningPath, Concept, Quote |
| **Marcus** | Fitness & Training | Training, Exercise, Program, PersonalRecord, BodyMetric |
| **Watson** | Relationship memory & emotional safety | Reflection, Value, Habit, LifeEvent, Intention, EmotionalMemory, RelationshipTheme, DialogueNote, DynamicPattern |
| **Bourdain** | Food & Cooking | Recipe, Restaurant, Ingredient, Meal, Technique |
| **Sophia** | Home, Food & Living Things | Recipe, Restaurant, Ingredient, Meal, Technique, Species, Plant, Tank, Garden, Ecosystem, Observation |
| **David** | Arts & Culture | Music, Film, Artwork, Playlist, Artist, Style, Fashion |
| **Cousteau** | Nature & Living Things | Species, Plant, Tank, Garden, Ecosystem, Observation |
| **Garth** | Personal Finance | Account, Investment, Asset, Liability, Budget, FinancialGoal |
| **Cristiano** | Football | Match, Team, League, Tournament, Player, Season |
@@ -46,6 +45,8 @@ MERGE (a)-[:RELATIONSHIP]->(b)
Watson replaces Seneca (as of 2026-04-28); Watson inherited Seneca's node types (Reflection, Value, Habit, LifeEvent, Intention) with a warmer, less goal-oriented framing. David replaces Bowie; David inherited Bowie's node types (Music, Film, Artwork, Playlist, Artist, Style) and added Fashion.
Sophia replaces **both** Bourdain and Cousteau (as of 2026-07-26) — a 2:1 merge. She inherited Bourdain's node types (Recipe, Restaurant, Ingredient, Meal, Technique) and Cousteau's (Species, Plant, Tank, Garden, Ecosystem, Observation) unchanged, reframing both around care of the home rather than culinary adventure or field naturalism. No node types were added or removed, and the constraints are keyed on node label rather than agent, so no migration was required.
## Cross-Team Reads
- **Work team:** Skill, Certification, Project, Client (context on professional life)

View File

@@ -101,7 +101,7 @@ SET n.title = $title,
```
`<self>` is your own agent name (a constant in the query body — `'from:harper'`,
`'from:bourdain'`, etc.). Everything else flows through `params`.
`'from:sophia'`, etc.). Everything else flows through `params`.
Example `params` (Harper sending Scotty a handoff):
@@ -136,11 +136,12 @@ to keep in sync.
| Team | Assistants |
|------|-----------|
| **Personal** | shawn, nate, hypatia, marcus, watson, bourdain, david, cousteau, garth, cristiano |
| **Personal** | shawn, nate, hypatia, marcus, watson, sophia, david, garth, cristiano |
| **Work** | alan, ann, jeffrey, jarvis, quentin |
| **Engineering** | scotty, harper, case |
Watson replaces Seneca (as of 2026-04-28); David replaces Bowie; Shawn is the
Watson replaces Seneca (as of 2026-04-28); David replaces Bowie; Sophia replaces
both Bourdain and Cousteau (as of 2026-07-26); Shawn is the
personal general assistant (calendar/contacts/email). Quentin is the work-team
solution architect; aws_sa is Quentin's subagent (called as a tool, not a
messaging peer) — see [work/subagents.md](../../work/subagents.md).

View File

@@ -3,8 +3,8 @@
> Canonical schema for the single shared graph database used by all AI assistants
---
version: 2.4.0
last_updated: 2026-06-19
version: 2.5.0
last_updated: 2026-07-26
replaces:
- prompts/personal/neo4j-schema.md (v1.0.0)
- prompts/work/neo4j-schema.md (v1.0.0)
@@ -32,9 +32,8 @@ This document defines the canonical schema for **one shared Neo4j graph database
| **Personal** | Hypatia | Learning & Reading | Read all, write own domain |
| **Personal** | Marcus | Fitness & Training | Read all, write own domain |
| **Personal** | Watson | Relationship Memory & Emotional Safety | Read all, write own domain |
| **Personal** | Bourdain | Food & Cooking | Read all, write own domain |
| **Personal** | Sophia | Home, Food & Living Things | Read all, write own domain |
| **Personal** | David | Arts & Culture | Read all, write own domain |
| **Personal** | Cousteau | Nature & Living Things | Read all, write own domain |
| **Personal** | Garth | Personal Finance | Read all, write own domain |
| **Personal** | Cristiano | Football | Read all, write own domain |
| **Work** | Alan | Strategy & Business Model | Read all, write `domain='work'` work nodes |
@@ -576,7 +575,7 @@ Relationships:
})
```
### Bourdain's Domain (Food & Cooking)
### Sophia's Domain Food (Recipe, Restaurant, Ingredient, Meal, Technique)
#### Recipe
```cypher
@@ -663,7 +662,7 @@ Relationships:
})
```
### Bowie's Domain (Arts & Culture)
### David's Domain (Arts & Culture)
#### Music
```cypher
@@ -762,7 +761,7 @@ Relationships:
})
```
### Cousteau's Domain (Nature & Living Things)
### Sophia's Domain Living Things (Species, Plant, Tank, Garden, Ecosystem, Observation)
#### Species
```cypher
@@ -1930,23 +1929,23 @@ If queries fail:
| 28 | RelationshipTheme | Personal | Watson | id |
| 29 | DialogueNote | Personal | Watson | id |
| 30 | DynamicPattern | Personal | Watson | id |
| 31 | Recipe | Personal | Bourdain | id |
| 32 | Restaurant | Personal | Bourdain | id |
| 33 | Ingredient | Personal | Bourdain | id |
| 34 | Meal | Personal | Bourdain | id |
| 35 | Technique | Personal | Bourdain | id |
| 31 | Recipe | Personal | Sophia | id |
| 32 | Restaurant | Personal | Sophia | id |
| 33 | Ingredient | Personal | Sophia | id |
| 34 | Meal | Personal | Sophia | id |
| 35 | Technique | Personal | Sophia | id |
| 36 | Music | Personal | David | id |
| 37 | Film | Personal | David | id |
| 38 | Artwork | Personal | David | id |
| 39 | Playlist | Personal | David | id |
| 40 | Artist | Personal | David | id |
| 41 | Style | Personal | David | id |
| 42 | Species | Personal | Cousteau | id |
| 43 | Plant | Personal | Cousteau | id |
| 44 | Tank | Personal | Cousteau | id |
| 45 | Garden | Personal | Cousteau | id |
| 46 | Ecosystem | Personal | Cousteau | id |
| 47 | Observation | Personal | Cousteau | id |
| 42 | Species | Personal | Sophia | id |
| 43 | Plant | Personal | Sophia | id |
| 44 | Tank | Personal | Sophia | id |
| 45 | Garden | Personal | Sophia | id |
| 46 | Ecosystem | Personal | Sophia | id |
| 47 | Observation | Personal | Sophia | id |
| 48 | Account | Personal | Garth | id |
| 49 | Investment | Personal | Garth | id |
| 50 | Asset | Personal | Garth | id |
@@ -1995,3 +1994,4 @@ If queries fail:
| 2.2.0 | 2026-04-28 | Watson replaces Seneca: renamed domain to "Relationship Memory & Emotional Safety", added EmotionalMemory/RelationshipTheme/DialogueNote/DynamicPattern (4 new node types), updated primary owner for Reflection/Value/Habit/LifeEvent/Intention to Watson. Total: 80 nodes, 15 assistants |
| 2.3.0 | 2026-05-17 | Added Shawn (Personal General Assistant). Promoted Contact and Task from Work-only to Universal with `domain='personal'\|'work'` disambiguating ownership (Shawn owns Personal; Jarvis/Jeffrey own Work). Event already had `domain` field — documented Shawn (personal) vs Jarvis (work) split explicitly. Added Communication node type (Shawn-owned, personal-only interaction history). Renamed Bowie → David in node-summary table. Corrected stale Seneca → Watson on Goal ownership. Documented strict Personal/Work scope divide and Kairos (Personal) vs Athena (Work) tool split. Total: 79 nodes, 16 assistants |
| 2.4.0 | 2026-06-19 | Added Quentin (Solution Architecture lead): Solution and Demo node types (Solution carries architecture + scope_of_work + effort_estimate as facets of one record), with FOR_CLIENT / HAS_DEMO / HAS_SOLUTION / PRESENTS / INVOLVES relationships. Repositioned AWS SA as Quentin's subagent (no node ownership). Added CASE (Field / physical layer) to the Teams & Assistants table — it was already a documented engineering lead but missing from this directory. Total: 81 nodes |
| 2.5.0 | 2026-07-26 | Sophia replaces **both** Bourdain and Cousteau (2:1 merge): renamed domain to "Home, Food & Living Things", updated primary owner for Recipe/Restaurant/Ingredient/Meal/Technique and Species/Plant/Tank/Garden/Ecosystem/Observation to Sophia. **No node types added or removed** — uniqueness constraints are keyed on node label, not agent, so no schema or data migration was required. Merged the two per-agent domain sections into one. Corrected stale `Bowie's Domain` heading to David (missed in 2.3.0). Total: 81 nodes, 17 assistants |

View File

@@ -11,7 +11,7 @@ Periplus is the canonical store for **places** in Robert's life: addresses and p
Named for the ancient Greek *periplus* — the sailing manual that listed coastal landmarks in order. Same idea: the catalogue of places that matter, with the routes between them.
Periplus sits in the same relation to Neo4j that Kairos does for calendar and contacts: Periplus holds the **canonical geographic record** (the lat/lng, the bookmark, the collection); Neo4j holds the **interpretation and cross-domain linking** (what Robert did at the place, what restaurant Bourdain recommended, what species Cousteau observed there).
Periplus sits in the same relation to Neo4j that Kairos does for calendar and contacts: Periplus holds the **canonical geographic record** (the lat/lng, the bookmark, the collection); Neo4j holds the **interpretation and cross-domain linking** (what Robert did at the place, what restaurant Sophia recommended, what species she observed there).
## ⚠️ Critical Discipline: Never Estimate Coordinates
@@ -87,9 +87,9 @@ Steps 1 and 3 enforce the no-estimate rule: the coordinates passed to `create_bo
## Who Uses Periplus
- **Nate** — heavy, primary. One collection per trip, with the destinations, lodging, day-trip points of interest. Used alongside `get_directions` for itinerary logistics.
- **Bourdain** — restaurants, markets, shops. Collections organized by city or by type. Bourdain's Neo4j `Restaurant` and `Ingredient` nodes cross-link to Periplus bookmarks.
- **Sophia** — restaurants, markets, butchers, nurseries, garden suppliers. Collections organized by city or by type. Sophia's Neo4j `Restaurant` and `Ingredient` nodes cross-link to Periplus bookmarks.
- **David** — stores, theatres, studios, apothecaries — the places where culture and good taste live. Collections by city or by type.
- **Cousteau** — site-of-interest bookmarks for nature observations (dive sites, garden suppliers, parks).
- **Shawn** — venues and addresses behind calendar events and contacts; the general-assistant catch-all for places that aren't anyone else's domain.
- **Other agents** read Periplus when their work involves a place; the four above do the writing.
## What It's Good For