Phase 8 follow-up: resolve the child named in the question
The Hub forwards `person` equal to the asker (`PersonOrDefault`), so the spoken question "what does Harry have on today at school?" arrives with person "sam" and returned "no data for that person" (found by the Hub agent on AUD-116). resolveChild now falls back to the question text when the requested person is not one of this project's children: whole-word, case-insensitive match against the child names this service already publishes in /capabilities. An explicit person still wins, two named children still return answer:null, and the permission check still runs on the resolved child. No model, no free text. Live end-to-end through the Hub, with no person field: POST http://192.168.20.13:8788/ask {"text":"what does Harry have on today at school?","asker":"sam","source":"console"} 200 {"status":"ok", "answer":"Harry has 8 school events today from 8:55am to 6:00pm and 6 overdue tasks.", "route":{"kind":"project","project":"compass_nhs"}} Image 0.6.1-phase8; docs/phase-8-hub-notes.md records the fallback and the end-to-end transcript. Co-Authored-By: Paperclip <noreply@paperclip.ing>
This commit is contained in:
@@ -89,6 +89,29 @@ Jo and Sam) may ask about any child, and anyone else may ask about themselves
|
||||
only. An unknown person returns `answer: null` with a reason; no data is leaked
|
||||
between the children.
|
||||
|
||||
### Which child the question is about
|
||||
|
||||
The contract makes `person` optional and says it defaults to `asker`. The Hub
|
||||
(as of AUD-116) forwards `person = asker`, so the spoken question *"what does
|
||||
Harry have on today at school?"* arrives with `person: "sam"`. Because this
|
||||
project is the expert on its own data, `resolveChild` falls back to the question
|
||||
text when the requested person is not one of its children:
|
||||
|
||||
- The requested `person` wins when it names a child (so an explicit `person` is
|
||||
never overridden).
|
||||
- Otherwise the question is split into whole words and matched,
|
||||
case-insensitively, against the child names this service already publishes in
|
||||
`/capabilities`.
|
||||
- Exactly one match resolves the child; two matches ("what do Harry and Finn
|
||||
have on?") return `answer: null` + a reason, because the contract answers for
|
||||
one person at most.
|
||||
- The permission check still runs on the resolved child.
|
||||
|
||||
No model and no free-text guessing are involved, and a name is never matched
|
||||
inside a longer word. This makes the Hub's current call shape answer correctly;
|
||||
[AUD-117](/AUD/issues/AUD-117) (the Hub deriving `person` itself) remains a
|
||||
useful Hub-side improvement, not a dependency of this phase.
|
||||
|
||||
## `/notify` — the interpretation
|
||||
|
||||
The contract defines `POST /notify` as project-to-Hub (the *project* posts to the
|
||||
@@ -118,7 +141,31 @@ make verify-phase8
|
||||
deploy/verify-phase8.sh --send
|
||||
```
|
||||
|
||||
## Evidence (2026-10-15, 08:46–08:47 UTC / 19:46–19:47 AEDT)
|
||||
## Evidence (2026-10-15)
|
||||
|
||||
### End-to-end through the live Hub (08:56 UTC / 19:56 AEDT)
|
||||
|
||||
The literal phase question, sent to the **Hub** on its inbound API with no
|
||||
`person` field, after [AUD-116](/AUD/issues/AUD-116) registered `compass_nhs`:
|
||||
|
||||
```
|
||||
POST http://192.168.20.13:8788/ask
|
||||
{"text":"what does Harry have on today at school?","asker":"sam","source":"console"}
|
||||
|
||||
200
|
||||
{
|
||||
"status": "ok",
|
||||
"request_id": "01M4ZC9G4TRXJ3MFSMJ66JSVQ1",
|
||||
"answer": "Harry has 8 school events today from 8:55am to 6:00pm and 6 overdue tasks.",
|
||||
"shape": "text",
|
||||
"route": {"kind": "project", "project": "compass_nhs"},
|
||||
"expires": "2026-10-15T13:00:00Z"
|
||||
}
|
||||
```
|
||||
|
||||
This is the Phase 8 definition of done: the Hub asks, and gets a correct answer.
|
||||
|
||||
### Against the service directly
|
||||
|
||||
`deploy/verify-phase8.sh` on `.13` against `http://127.0.0.1:8792`:
|
||||
|
||||
@@ -164,30 +211,20 @@ hub notify delivered from=verify-phase8 level=info recipient=Sam channel=email
|
||||
hub notify delivered from=verify-phase8 level=info recipient=Sam channel=whatsapp status=200
|
||||
```
|
||||
|
||||
## The Hub wiring (remaining)
|
||||
## The Hub wiring (done)
|
||||
|
||||
The Hub container (`central-ai-hub:local`, port 8788) currently runs with
|
||||
`HUB_PROJECTS` empty, so it has no data project to route to. Registering this
|
||||
service and restarting the Hub is a change to a running, family-used service and
|
||||
a change to `~/.config/environment.d/10-secrets.conf`, so it is done only with a
|
||||
recorded approval.
|
||||
The Hub container (`central-ai-hub:local`, port 8788) now has this service
|
||||
registered. The change was made by the Hub agent on
|
||||
[AUD-116](/AUD/issues/AUD-116):
|
||||
|
||||
The change is exactly:
|
||||
1. `~/.config/environment.d/10-secrets.conf` gained
|
||||
`HUB_PROJECT_COMPASS_NHS_TOKEN` and `compass_nhs=http://192.168.20.13:8792`
|
||||
in `HUB_PROJECTS` (alongside `email_agent` and `internet_control`).
|
||||
2. The `hub` container was restarted once, bounded.
|
||||
3. The transcript above is the result.
|
||||
|
||||
1. Add to `~/.config/environment.d/10-secrets.conf`:
|
||||
`HUB_PROJECT_COMPASS_NHS_TOKEN=<the value of SCHOOL_HUB_TOKEN in this project's environment.d/school-service.env>`.
|
||||
2. Set `HUB_PROJECTS` there to include
|
||||
`compass_nhs=http://192.168.20.13:8792` (keep the existing `email_agent` entry).
|
||||
3. Restart the `hub` container: `docker compose -f /home/sam/paseo/projects/central_ai_llm_master/docker-compose.yml up -d hub`.
|
||||
|
||||
Then the end-to-end check is:
|
||||
|
||||
```bash
|
||||
curl -sS -H "Authorization: Bearer $HUB_TOKEN_CONSOLE" -H 'Content-Type: application/json' \
|
||||
-d '{"text":"what does Harry have on today at school?","asker":"sam","source":"console"}' \
|
||||
http://192.168.20.13:8788/ask
|
||||
# expect route.kind = project, route.project = compass_nhs, status ok
|
||||
```
|
||||
`routing.md` was not changed: the `compass_nhs` row already existed and matches
|
||||
this service's `/capabilities` name.
|
||||
|
||||
## Decisions and notes
|
||||
|
||||
|
||||
Reference in New Issue
Block a user