feat(ai): retrieval evals, in-app tools, and the AI quality gaps 0394 found - #629
Merged
Merged
Conversation
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Signed-off-by: xNet Test <test@xnet.dev>
Scoped AI search filtered a cross-schema BM25 window after loading, so a schemaId-scoped query returned fewer than the requested limit whenever that schema's matches ranked below the window. searchNodes now joins nodes and filters in SQL (soft-deleted rows excluded there too); the service-side post-filter stays as a guard for adapters that ignore the new option. When BM25 is unavailable the search response says so - index: 'scan', degraded: true, a reason, and a notice telling the model not to conclude something is absent from a truncated substring scan. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Signed-off-by: xNet Test <test@xnet.dev>
The packaged Electron CSP denied everything the WebLLM and vector tiers need: model-weight hosts, WebAssembly compilation, blob workers, and the 127.0.0.1 loopback the connector ladder probes for the agent bridge and Ollama (it allowed localhost only, which does not cover it). Also documents why the web build's connect-src keeps a bare https://* -- it carries crash-report ingest and the sync socket for user-configured custom hubs, origins no static policy can name -- and pins both policies with a test so the AI hosts cannot regress silently. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Signed-off-by: xNet Test <test@xnet.dev>
The repo measured agent interfaces (token cost per task) but nothing measured retrieval output, so every change to the retriever shipped on reasoning alone. Adds a pinned corpus, 13 golden queries, and recall@k / MRR over the real retrieve() pipeline, gated against a committed baseline that ratchets. Scored at k=5: at k=12 every case recalls 1.00 on a corpus this size and the gate could never fail. It carries its own mutation tests, so a broken graph or entry stage reddens it. Sweeping HOP_DECAY meant making it injectable (RetrievalBudget.hopDecay). The result is a null one worth recording: everything in [0.35, 0.85] scores identically and the nominal winner leads by a single golden item, under the eval's resolution. 0.55 stays, now with evidence rather than a bare literal. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Signed-off-by: xNet Test <test@xnet.dev>
Rule 2 of the enhancement contract is 'never invent facts, numbers, names, or commitments' - the failure that makes AI notes worse than none, since a fabricated commitment is indistinguishable from a real one once written down. Nothing checked it. Adds screenGroundedness(): flags numbers and name-positioned words that appear in neither the transcript nor the user's notes, plus fixtures for faithful and hallucinated output. List items are checked from their first word, where action-item owners live; prose skips the sentence-initial capital, which is grammar rather than a name. It is a screen, not a proof - it cannot catch a plausible claim built only from words already present - and it says so. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Signed-off-by: xNet Test <test@xnet.dev>
The 28 xnet_* tools reached MCP clients, the CLI and the bridge, but never the in-app chat - it could only answer from whatever the context pack happened to retrieve, and said so in its own system prompt. AiAgentRuntime now runs a bounded tool loop, and the panel hands it a read-only subset (search, read page, database describe/query/sample, graph expand, canvas read, audit log) on tiers that call tools reliably. Weak and non-calling tiers keep the context-pack-only path, since giving them tools produces invention rather than grounding. Phase 1 is read-only by construction: the allow-list requires both an explicit name and a low risk rating, so neither adding a low-risk tool to the registry nor reclassifying an existing one can widen what the chat reaches. Writes wait on an in-chat approval ceremony. Also fixes a settle bug the loop exposed: model.completed fires once per round trip, so treating it as end-of-turn truncated the reply at the first tool call. Only run.* settles now. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Signed-off-by: xNet Test <test@xnet.dev>
…hniques (9/17) Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Signed-off-by: xNet Test <test@xnet.dev>
Contributor
🖼️ UI changes in this PRScreensAuto-captured by CI · run. Informational — not a blocking check. |
Contributor
|
Preview removed for PR #629. |
Additive: an optional third parameter on the three searchText declarations plus the new NodeTextSearchOptions interface. Confirms the minor bump. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Signed-off-by: xNet Test <test@xnet.dev>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.



Implements exploration 0394 — a retrospective map of how AI is integrated in xNet, and the gaps it found. 9/17 checklist items; 7 of 10 implementation items.
What this fixes
The repo measured agent interfaces but never AI outputs. The token benchmark was the only eval. So every retrieval improvement shipped on reasoning alone.
packages/brain/src/__evals__/) — pinned corpus, 13 queries, recall@k + MRR over the realretrieve()pipeline, gated on a committed baseline that ratchets. Scored at k=5: at k=12 every case recalls 1.00 and the gate could never fail. Carries its own mutation tests, so a broken graph or entry stage reddens it.HOP_DECAYswept for real — and the honest result is a null one: everything in [0.35, 0.85] scores identically, and the nominal winner (0.20) leads by 0.04, which is one golden item on a 13-query set, under the eval's own resolution. 0.55 stays — not vindicated, just unfalsified. The gate fails if anything ever beats it by more than one item.RRF_Kdeliberately not swept. It needs a genuinely semantic second ranker; a mock model measures the mock, and real MiniLM weights mean a network download in a lane that must not flake.screenGroundedness()flags numbers and name-positioned words absent from the transcript and the user's notes. It's a screen, not a proof, and says so.Scoped AI search silently under-returned.
schemaIdwas filtered after loading a cross-schema BM25 window, so a scoped query came back near-empty whenever that schema's matches ranked below the window. Now pushed into SQL (verified against real FTS5).A search that fell back to a scan looked identical to an exhaustive one — so the model would state "no such node" with unearned confidence. Responses now carry
index,degraded, and a notice.On-device AI was dead in the packaged desktop app. The Electron CSP denied model-weight hosts, WebAssembly, blob workers, and the
127.0.0.1loopback the connector ladder actually probes (it allowedlocalhostonly, which doesn't cover it). Both shells are now pinned by a contract test.The in-app assistant had zero tools — the 28
xnet_*tools reached MCP clients, the CLI and the bridge, but not the chat.AiAgentRuntimenow runs a bounded tool loop, and the panel hands it a read-only subset on tiers that call tools reliably. Weak tiers keep the context-pack path, since tools there produce invention rather than grounding. Tool activity is visible while it runs.Fixes a settle bug the loop exposed:
model.completedfires once per round trip, so treating it as end-of-turn truncated the reply at the first tool call.What I did NOT do, on purpose
The web
connect-srcwildcard stays. The checklist said remove it; the inventory says you can't.https://*was added inc8e2e96ad(0341) so crash-report ingest reaches a user-configured custom hub, andwss://*carries its sync socket. Those origins are typed at runtime — no static meta-tag policy can name them. Removing it drops custom-hub support from the web build. That's a product decision with a migration story, not a cleanup. Documented in place and pinned by test. (Link previews are not affected — they proxy through the hub's SSRF-guarded/unfurl.)Phase 2 (in-chat approval) and the
/v1/agent/streamclient are deferred. Phase 2 is the gate that makes writes safe; shipping it half-built is worse than not shipping it — a flow that looks trustworthy but mishandles the medium-risk nonce trains users to click through. The stream client is deferred with it, because its payoff is thepermission_requestframe Phase 2 renders. Rationale and the seams they extend are in the doc.Verification
data-bridge/binary-state(a package this branch doesn't touch; passes in isolation at 30ms vs a 490ms threshold).apps/web,plugins,brain,meetings.files-cli2728 /mcp-slim18260 /mcp-legacy24346 tokens, 15/15 each — in-app tools are app-side and never touch the MCP surface.all=0.81 keyword=1.00 graph=0.50 mrr=0.69. Thegraph=0.50is real headroom, recorded rather than hidden.🤖 Generated with Claude Code