- docs/phase-4-corpus.md rewritten: Gitea (all repos), vault via Gitea, Graphify graph, curated content as tier 1. Platform guides are config and public copy. - docs/phase-5-ai-overlay.md: citations to originals, tier preference, live source readout. - Board: AUD-144 (index content/ only) retired; AUD-147 replaces it, blocked by AUD-141 and AUD-142. AUD-145 relinked to AUD-143 and AUD-147.
123 lines
4.9 KiB
Markdown
123 lines
4.9 KiB
Markdown
# Phase 5 — Mode B console (the AI overlay)
|
|
|
|
**Goal:** a prompt box that streams a short, cited answer and can take over the stage panel. The AI is a second driver for the same panel, not a second site.
|
|
|
|
**Depends on:** Phase 3 (live URL), Phase 4 (corpus).
|
|
|
|
---
|
|
|
|
## Work
|
|
|
|
### 5.1 Query path
|
|
|
|
```
|
|
question
|
|
→ rate limit (per IP)
|
|
→ CLASSIFY fast tier intent · injection score · off-topic · PII
|
|
├─ refuse → fixed message, zero model spend
|
|
└─ allow
|
|
→ ROUTE fast tier which area(s) to search
|
|
→ RETRIEVE Qdrant (payload-filtered) + SQLite FTS5
|
|
→ reciprocal rank fusion → cross-encoder rerank top-20 → top-5
|
|
→ COMPOSE mid tier answer ONLY from context, inline citations
|
|
→ VERIFY citation presence + claim supported by context
|
|
→ STREAM SSE
|
|
```
|
|
|
|
Four nodes. If the graph needs more than four to work, stop and report — complexity growth here is the failure mode this project exists to avoid.
|
|
|
|
### 5.2 Transport
|
|
- `GET /api/ask` as Server-Sent Events.
|
|
- Three event types: `token`, `meta` (route, timings, tokens, cost), `done`.
|
|
- **Never buffer SSE.** Verify with `flush_interval -1` on the proxy if streams stall. No gzip on the API path.
|
|
|
|
### 5.3 The console (the only client-side code in the project)
|
|
One hand-written TypeScript island, ES modules, no framework, no bundler.
|
|
|
|
- `xterm.js` console showing the pipeline live: route, retrieval count, timings, tokens, cost.
|
|
- Prompt box with submit and stop.
|
|
- Stage panel driven by the `token` stream — the driver built in Phase 2 §2.4.
|
|
- Panel clears on new response and on navigation.
|
|
- Footer strip: model · latency · tokens · cost.
|
|
|
|
### 5.4 Citations
|
|
- Every factual claim carries a citation to a `content/` page or artefact.
|
|
- Citation URLs validated against the known-artefact allow-list; unknown URLs dropped, not rendered.
|
|
- Answer shape: direct answer → specifics → evidence pointer → optional single suggestion (per `agents/persona.md`).
|
|
|
|
### 5.5 Persona
|
|
- Load `agents/persona.md` at runtime. It is a file, versioned, not a string in code.
|
|
- Test the tone: a short answer, an honest "not in the corpus" answer, and a "here's the better example for your role" answer.
|
|
|
|
---
|
|
|
|
## Definition of Done
|
|
|
|
- [ ] First token < 4 s; complete answer < 15 s at p90, measured and recorded.
|
|
- [ ] Every claim in ten sample answers resolves to a real page or artefact. No dangling citations.
|
|
- [ ] The panel is driven by the SSE stream without changes to layout code (proves Phase 2 §2.4 held).
|
|
- [ ] The island is the **only** client-side application code; no framework, no bundler, no `node_modules`.
|
|
- [ ] A and B do not drift: for any question, the answer's claims exist on the site.
|
|
- [ ] SSE streams untruncated at p90 with no cancellation leak when the client disconnects.
|
|
- [ ] All model calls go through OmniRoute; grep proves no direct provider call exists.
|
|
- [ ] Asking an off-topic question produces a short refusal and costs nothing.
|
|
|
|
---
|
|
|
|
## Out of scope
|
|
|
|
- Guardrail hardening, cost ceilings and the kill switch — **Phase 6**. Phase 5 runs with a permissive guard and no public traffic.
|
|
- Voice input.
|
|
- Hub `/ask` registration (a follow-on task, not this phase).
|
|
|
|
---
|
|
|
|
## Risks
|
|
|
|
| Risk | Mitigation |
|
|
|---|---|
|
|
| Graph grows past four nodes | Hard review gate: report and justify before adding a fifth |
|
|
| Panel refactor needed | Phase 2 §2.4 contract; if it fails, fix the panel contract, do not fork the UI |
|
|
| Streaming stalls behind Caddy | Explicit flush settings; p90 measurement, not a spot check |
|
|
| Answers drift from the site | Citation verification is a node, not a hope |
|
|
|
|
---
|
|
|
|
## 5.6 Citations point at the original
|
|
|
|
An answer cites where it came from, not a curated page standing in for it.
|
|
|
|
| Source | Cited as |
|
|
|---|---|
|
|
| Gitea repo file | full URL to the file in Gitea |
|
|
| Vault note | full URL to the note in `sam/obsidian-vault` |
|
|
| Graph answer | the note title the node came from, plus its URL |
|
|
| Curated claim | the site page |
|
|
|
|
A citation whose URL cannot be opened is dropped, not rendered. A claim with no
|
|
traceable origin is not returned at all.
|
|
|
|
## 5.7 Curated outranks harvested
|
|
|
|
`content/` is tier 1; everything harvested is tier 2. When the two disagree, the
|
|
tier 1 claim wins and the answer says so plainly: the curated description is
|
|
current; the older text is background.
|
|
|
|
This is the rule that stops a stale README from quietly overwriting Sam's own
|
|
description of his work.
|
|
|
|
## 5.8 The live source readout
|
|
|
|
While the answer streams, a panel shows what is being read, named as the visitor
|
|
would recognise it:
|
|
|
|
```
|
|
reading · gitea/photo-pipeline/README.md
|
|
· obsidian/210 AI Resume/Graphify.md
|
|
· graph · community 42 · vault infrastructure
|
|
```
|
|
|
|
This is a feature, not a debug view. It answers the question every recruiter has
|
|
and does not ask: is this making things up? Show the working — it is also the most
|
|
convincing demonstration of the system on the page.
|