Skip to content

feat(ai): retrieval evals, in-app tools, and the AI quality gaps 0394 found - #629

Merged
crs48 merged 8 commits into
mainfrom
claude/0394-ai-integration-and-quality-techniques
Jul 25, 2026
Merged

feat(ai): retrieval evals, in-app tools, and the AI quality gaps 0394 found#629
crs48 merged 8 commits into
mainfrom
claude/0394-ai-integration-and-quality-techniques

Conversation

@crs48

@crs48 crs48 commented Jul 24, 2026

Copy link
Copy Markdown
Owner

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.

  • Golden-set retrieval eval (packages/brain/src/__evals__/) — pinned corpus, 13 queries, recall@k + MRR over the real retrieve() 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_DECAY swept 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_K deliberately 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.
  • Groundedness screen for meeting notes — contract rule 2 is "never invent", and nothing checked it. 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. schemaId was 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.1 loopback the connector ladder actually probes (it allowed localhost only, 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. AiAgentRuntime now 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.

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.

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.

What I did NOT do, on purpose

The web connect-src wildcard stays. The checklist said remove it; the inventory says you can't. https://* was added in c8e2e96ad (0341) so crash-report ingest reaches a user-configured custom hub, and wss://* 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/stream client 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 the permission_request frame Phase 2 renders. Rationale and the seams they extend are in the doc.

Verification

  • Full suite: 11133 passed, 1 pre-existing timing flake in data-bridge/binary-state (a package this branch doesn't touch; passes in isolation at 30ms vs a 490ms threshold).
  • Typecheck clean across apps/web, plugins, brain, meetings.
  • Agent-surface benchmark unchanged: files-cli 2728 / mcp-slim 18260 / mcp-legacy 24346 tokens, 15/15 each — in-app tools are app-side and never touch the MCP surface.
  • Retrieval eval baseline: recall@5 all=0.81 keyword=1.00 graph=0.50 mrr=0.69. The graph=0.50 is real headroom, recorded rather than hidden.

🤖 Generated with Claude Code

xNet Test and others added 7 commits July 24, 2026 15:52
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>
@crs48
crs48 temporarily deployed to pr-629 July 24, 2026 23:49 — with GitHub Actions Inactive
@github-actions

github-actions Bot commented Jul 24, 2026

Copy link
Copy Markdown
Contributor

🖼️ UI changes in this PR

Screens

✏️ Home _(SSIM 0.981)_
before after diff
before after diff

Auto-captured by CI · run. Informational — not a blocking check.

github-actions Bot added a commit that referenced this pull request Jul 24, 2026
github-actions Bot added a commit that referenced this pull request Jul 24, 2026
@github-actions

github-actions Bot commented Jul 24, 2026

Copy link
Copy Markdown
Contributor

Preview removed for PR #629.

github-actions Bot added a commit that referenced this pull request Jul 24, 2026
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>
@crs48
crs48 temporarily deployed to pr-629 July 24, 2026 23:59 — with GitHub Actions Inactive
github-actions Bot added a commit that referenced this pull request Jul 25, 2026
github-actions Bot added a commit that referenced this pull request Jul 25, 2026
github-actions Bot added a commit that referenced this pull request Jul 25, 2026
@crs48
crs48 merged commit 3b53b23 into main Jul 25, 2026
22 checks passed
@crs48
crs48 deleted the claude/0394-ai-integration-and-quality-techniques branch July 25, 2026 00:08
github-actions Bot added a commit that referenced this pull request Jul 25, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant