<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Meaning Graph on Boris Dupoux</title><link>https://borisdupoux.com/tags/meaning-graph/</link><description>Recent content in Meaning Graph on Boris Dupoux</description><generator>Hugo -- gohugo.io</generator><language>en-us</language><lastBuildDate>Sun, 11 Oct 2026 00:00:00 +0000</lastBuildDate><atom:link href="https://borisdupoux.com/tags/meaning-graph/index.xml" rel="self" type="application/rss+xml"/><item><title>A Fully Local AI Agent with a Meaning Graph and Multimodal Emotion Measurement</title><link>https://borisdupoux.com/research/local-ai-agent/</link><pubDate>Sun, 11 Oct 2026 00:00:00 +0000</pubDate><guid>https://borisdupoux.com/research/local-ai-agent/</guid><description>&lt;h2 id="context"&gt;&lt;a href="#context" class="header-anchor"&gt;&lt;/a&gt;Context
&lt;/h2&gt;&lt;p&gt;Personal digital traces (messaging, mail, photos, music listening, notes, calendar,
health exports, code repositories) are among the most sensitive data a person owns, and
also among the richest for studying behaviour — and feeling — over time. Sending them to
a cloud LLM is not acceptable, so everything here runs on a single Apple-silicon desktop
(M4, 32 GB unified memory). No personal content is sent to a cloud model; the only
outbound request is an opt-in lookup of public 30 s previews (artist and title) on Apple&amp;rsquo;s
iTunes search.&lt;/p&gt;
&lt;p&gt;The aim is an agent that answers questions about one&amp;rsquo;s own life while keeping a strict
line between what is &lt;em&gt;observed&lt;/em&gt;, what is &lt;em&gt;computed&lt;/em&gt;, what is &lt;em&gt;hypothesised by a model&lt;/em&gt;,
and what is &lt;em&gt;accepted as true by its owner&lt;/em&gt;.&lt;/p&gt;
&lt;h2 id="what-is-original"&gt;&lt;a href="#what-is-original" class="header-anchor"&gt;&lt;/a&gt;What is original
&lt;/h2&gt;&lt;p&gt;Local agents over personal files are not new. Two aspects of this project are.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;1. A meaning graph on top of a measurement layer.&lt;/strong&gt; Knowledge is held at two levels.
An &lt;em&gt;observatory&lt;/em&gt; stores facts and signals in long format (item, dimension, value,
confidence, model, version). Above it, a &lt;strong&gt;meaning graph&lt;/strong&gt; stores what those signals
&lt;em&gt;mean&lt;/em&gt;: &lt;strong&gt;relations&lt;/strong&gt; (reified, so that a relationship can evolve and be measured),
&lt;strong&gt;affective episodes&lt;/strong&gt; (who felt what, when, how intensely, through which modality),
&lt;strong&gt;themes&lt;/strong&gt;, &lt;strong&gt;chapters&lt;/strong&gt; of a life, and &lt;strong&gt;truths&lt;/strong&gt; — statements with supporting and
contradicting evidence that only the owner can validate. Every node and edge carries its
provenance down to the source element, and one of 9 origins in 6 trust ranks
(declared &amp;gt; structural &amp;gt; rule/computed &amp;gt; vendor &amp;gt; model — image, text or audio —&lt;/p&gt;

 &lt;blockquote&gt;
 &lt;p&gt;inferred), with a recorded human decision always taking precedence.&lt;/p&gt;

 &lt;/blockquote&gt;
&lt;p&gt;&lt;strong&gt;2. Emotion measured across modalities, along unusual dimensions.&lt;/strong&gt; The same fixed
vocabulary of &lt;strong&gt;53 emotions&lt;/strong&gt; (Plutchik-based, each with valence and arousal coordinates)
is applied to &lt;strong&gt;messages&lt;/strong&gt; (local LLM), &lt;strong&gt;voice&lt;/strong&gt; (five acoustic and multimodal layers,
three of them fused with the transcript, with an explicit text/voice &lt;em&gt;mismatch&lt;/em&gt; flag) and
&lt;strong&gt;photos&lt;/strong&gt; (deterministic colour and light measures, SigLIP embeddings, face signals
specified as weak evidence). These sit in a catalogue of &lt;strong&gt;929 defined dimensions in 88
groups&lt;/strong&gt; that goes well beyond the usual metadata. A few examples of its less common
entries (rows marked † are defined, not yet computed):&lt;/p&gt;
&lt;table&gt;
	&lt;thead&gt;
			&lt;tr&gt;
					&lt;th&gt;modality&lt;/th&gt;
					&lt;th&gt;dimension&lt;/th&gt;
					&lt;th&gt;how it is defined&lt;/th&gt;
			&lt;/tr&gt;
	&lt;/thead&gt;
	&lt;tbody&gt;
			&lt;tr&gt;
					&lt;td&gt;photo&lt;/td&gt;
					&lt;td&gt;colour temperature&lt;/td&gt;
					&lt;td&gt;mean red–blue balance of the image (warm vs cool)&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;photo&lt;/td&gt;
					&lt;td&gt;colourfulness&lt;/td&gt;
					&lt;td&gt;Hasler &amp;amp; Süsstrunk (2003) opponent-colour metric&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;photo&lt;/td&gt;
					&lt;td&gt;golden hour / blue hour †&lt;/td&gt;
					&lt;td&gt;sun elevation computed offline from date and position&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;photo&lt;/td&gt;
					&lt;td&gt;face size&lt;/td&gt;
					&lt;td&gt;share of the frame taken by a face (a proxy for proximity)&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;voice&lt;/td&gt;
					&lt;td&gt;jitter, shimmer, harmonics-to-noise ratio&lt;/td&gt;
					&lt;td&gt;openSMILE eGeMAPS prosody&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;voice&lt;/td&gt;
					&lt;td&gt;laughter, crying, sighs&lt;/td&gt;
					&lt;td&gt;sound-event detection (AudioSet classes)&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;voice&lt;/td&gt;
					&lt;td&gt;text/voice mismatch&lt;/td&gt;
					&lt;td&gt;voice valence and transcript valence differ by ≥ 0.6&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;message&lt;/td&gt;
					&lt;td&gt;valence, arousal, tone&lt;/td&gt;
					&lt;td&gt;per participant, constrained to the fixed grid&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;message&lt;/td&gt;
					&lt;td&gt;expressive punctuation, emoji palette †&lt;/td&gt;
					&lt;td&gt;deterministic text measures&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;relation&lt;/td&gt;
					&lt;td&gt;reply-latency asymmetry †&lt;/td&gt;
					&lt;td&gt;log ratio of the two parties&amp;rsquo; median reply delays&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;relation&lt;/td&gt;
					&lt;td&gt;initiatives&lt;/td&gt;
					&lt;td&gt;conversations opened after 3 h of silence, per side&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;relation&lt;/td&gt;
					&lt;td&gt;trend †&lt;/td&gt;
					&lt;td&gt;slope of relationship intensity over 90 days (cooling &amp;lt; 0)&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;period&lt;/td&gt;
					&lt;td&gt;musical nostalgia †&lt;/td&gt;
					&lt;td&gt;mean age of the tracks listened to&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;period&lt;/td&gt;
					&lt;td&gt;creation / consumption †&lt;/td&gt;
					&lt;td&gt;time in creative tools ÷ time consuming&lt;/td&gt;
			&lt;/tr&gt;
	&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;† defined, not yet computed.&lt;/p&gt;
&lt;h2 id="from-signals-to-meaning"&gt;&lt;a href="#from-signals-to-meaning" class="header-anchor"&gt;&lt;/a&gt;From signals to meaning
&lt;/h2&gt;&lt;pre class="mermaid" style="visibility:hidden"&gt;flowchart LR
 PH["Photo"] --&gt; PM["Measures&lt;br/&gt;light · contrast · colour temperature&lt;br/&gt;colourfulness · palette · sharpness"]
 PH --&gt; PS["SigLIP embedding&lt;br/&gt;(image ↔ text similarity)"]
 PH --&gt; PF["Vendor face signals&lt;br/&gt;smile · expression · gaze · face size"]
 VN["Voice note"] --&gt; VT["Whisper transcript"]
 VN --&gt; VL["Acoustic layers&lt;br/&gt;valence/arousal/dominance · categories&lt;br/&gt;sound events · prosody · audio-LLM"]
 VT --&gt; VX["Text emotion of transcript"]
 VL --&gt; VF["Weighted fusion&lt;br/&gt;confidence = agreement&lt;br/&gt;text/voice mismatch flag"]
 VX --&gt; VF
 MS["Messages&lt;br/&gt;(pseudonymised: Me, P1, P2)"] --&gt; ML["Local LLM, fixed grid&lt;br/&gt;emotion · intensity · valence&lt;br/&gt;arousal · tone · topics"]
 PM --&gt; OB[("Observatory&lt;br/&gt;929 dimensions")]
 PS --&gt; OB
 PF --&gt; OB
 VF --&gt; OB
 ML --&gt; OB
 OB -- "emotion with enough confidence" --&gt; AFF["Affective episode (AFF)&lt;br/&gt;who · emotion · when · intensity · modality"]
 PF -. "planned: weak cue, confidence ≤ 0.4" .-&gt; AFF
 ML -- "topics" --&gt; THM["Themes"]
 OB -- "aggregates" --&gt; AG["Day / period indicators&lt;br/&gt;valence · light · palette"]
 AFF --&gt; G["Meaning graph&lt;br/&gt;relations · episodes · themes · chapters · truths&lt;br/&gt;(all proposed)"]
 THM --&gt; G
 AG --&gt; G
 G --&gt; HV(("Owner&lt;br/&gt;validate · reject · correct"))&lt;/pre&gt;&lt;p&gt;Each affective episode is a node linked to the person who felt it, to the emotion in the
fixed vocabulary, and — when it exists — to the conversation or moment it occurred in.
Inference rules then carry affect upwards (for instance, the affect of a chapter or of a
routine), and strong aggregate correlations can become &lt;em&gt;proposed&lt;/em&gt; truths with their
measures as evidence.&lt;/p&gt;
&lt;h2 id="emotion-measurement-in-detail"&gt;&lt;a href="#emotion-measurement-in-detail" class="header-anchor"&gt;&lt;/a&gt;Emotion measurement in detail
&lt;/h2&gt;&lt;p&gt;&lt;strong&gt;Vocabulary.&lt;/strong&gt; The grid is fixed and versioned: Plutchik&amp;rsquo;s 8 primary emotions at 3
intensities, his 8 primary dyads, plus social and reflective emotions useful for a life
(gratitude, tenderness, pride, shame, loneliness, nostalgia, wonder, relief, exhaustion…),
&lt;strong&gt;53 in total&lt;/strong&gt;. Each carries starting coordinates in Russell&amp;rsquo;s circumplex — valence in
[−1, 1], arousal in [0, 1] — meant to be calibrated later on the owner&amp;rsquo;s own validations.
Plutchik oppositions are encoded, and health-app mood labels are mapped onto the grid.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Messages.&lt;/strong&gt; A local LLM (Qwen3-30B-A3B) reads each conversation with participants
replaced by &amp;ldquo;Me&amp;rdquo;, &amp;ldquo;P1&amp;rdquo;, &amp;ldquo;P2&amp;rdquo;, messages framed as data it must not obey, and media
reduced to placeholders such as &amp;ldquo;[voice note 23 s]&amp;rdquo;. Output is constrained by a JSON
schema: for each participant, the dominant emotion from the grid (or none), intensity,
valence, arousal, a tone from a closed list of 19, and a confidence; plus 1–3 topics
that become themes. Long conversations are reduced to their beginning and end; short
ones are batched ten per call. An affective episode is proposed only when confidence is
at least 0.3.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Voice.&lt;/strong&gt; Each recording is converted to 16 kHz mono and passes through:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Whisper large-v3-turbo (MLX) for the transcript;&lt;/li&gt;
&lt;li&gt;a wav2vec2 dimensional model giving valence, arousal and dominance on 15 s windows,
weighted by window length, plus arousal variability;&lt;/li&gt;
&lt;li&gt;emotion2vec+ large for categorical emotion, mapped onto the grid (kept at ≥ 0.4);
its labels cover only 6 of the 53 emotions;&lt;/li&gt;
&lt;li&gt;an AST AudioSet classifier for laughter, crying, sighs, shouting, whispering, music
and ambience;&lt;/li&gt;
&lt;li&gt;openSMILE eGeMAPS prosody: pitch (semitones) and its variability, loudness, jitter,
shimmer, harmonics-to-noise ratio, voiced segments per second, mean pause length;&lt;/li&gt;
&lt;li&gt;Qwen2.5-Omni-7B (llama.cpp, Metal), which listens to the audio and returns an emotion
from the grid, a valence and short acoustic cues;&lt;/li&gt;
&lt;li&gt;the text-emotion model above, applied to the transcript.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Only wav2vec2, emotion2vec+, Qwen2.5-Omni and the transcript enter the fusion; sound
events and prosody are kept as separate signals. The categorical opinions (voice
categories, audio-LLM, transcript) are combined by a
weighted vote (weights 1.0, 1.0 and 0.8); valence is a weighted mean of the dimensional
model, the audio-LLM and the transcript. &lt;strong&gt;Confidence is agreement between layers&lt;/strong&gt;: one
agreeing source gives 0.45, two give 0.65, three give 0.85, minus 0.1 for each source
that disagrees. When the voice and the words disagree by 0.6 or more in valence (an
&amp;ldquo;I&amp;rsquo;m fine&amp;rdquo; said sadly), a &lt;strong&gt;text/voice mismatch&lt;/strong&gt; is flagged rather than averaged away.
Laughter and crying scores are kept alongside.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Photos.&lt;/strong&gt; On 256 px thumbnails, without any model: luminance, contrast, saturation,
colour temperature, colourfulness, sharpness (variance of the Laplacian) and a 5-colour
palette with named dominant hue. SigLIP so400m embeddings make the library searchable by
text. Vendor face attributes (smile, smile type, expression, gaze, eye state, face size)
are read as signals, but the schema states that &lt;em&gt;a photographed smile is not a felt joy&lt;/em&gt;:
the face modality is specified as a weak cue whose confidence is to be capped at 0.4
(planned, not yet implemented). Music mood is handled the same way: the mood of a track is
never, on its own, evidence of the listener&amp;rsquo;s mood. At period level, valence is specified
to be fused with a fixed precedence, declared &amp;gt; voice &amp;gt; text &amp;gt; face (planned, not yet
implemented).&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Human validation.&lt;/strong&gt; Every episode, theme, chapter or truth is emitted as &lt;code&gt;proposed&lt;/code&gt;.
The PWA shows a validation queue — affective episodes ordered by confidence, with the
evidence (the conversation or recording it came from) — and the owner validates, rejects
or corrects. Only that human decision event turns a proposal into &lt;code&gt;validated&lt;/code&gt;, an
equivalence checked automatically. The planned next step is a small personal classifier
on emotion2vec features, trained on these validations.&lt;/p&gt;
&lt;h2 id="architecture"&gt;&lt;a href="#architecture" class="header-anchor"&gt;&lt;/a&gt;Architecture
&lt;/h2&gt;&lt;pre class="mermaid" style="visibility:hidden"&gt;flowchart TB
 S["Sources (read-only snapshots)&lt;br/&gt;messaging · mail · photos · music · notes · calendar · exports"]
 C["Connectors&lt;br/&gt;dedicated ingestion process, sole holder of disk access"]
 V["Vault (owner-only, 0700)&lt;br/&gt;content-addressed raw store"]
 O["Observatory&lt;br/&gt;facts + signals (SQLite)"]
 K["Meaning graph&lt;br/&gt;append-only JSONL log → SQLite fold + FTS"]
 N["Nightly / hourly pipelines&lt;br/&gt;thumbnails · measures · SigLIP · emotions&lt;br/&gt;(GPU lock, one model at a time)"]
 M["MCP server (stdio, no port)&lt;br/&gt;41 read-only / propose-only tools&lt;br/&gt;20 exposed to the agent"]
 H["Hermes Agent&lt;br/&gt;local LLM via Ollama"]
 P["PWA (HTTPS + TOTP)&lt;br/&gt;chat · validation queue"]
 U(("Owner"))
 S --&gt; C --&gt; V --&gt; O --&gt; K
 N --&gt; O
 O --&gt; M
 K --&gt; M
 M --&gt; H --&gt; P
 P -- "validate / reject / correct" --&gt; K
 U -- "NetBird VPN" --&gt; P&lt;/pre&gt;&lt;p&gt;Raw data is snapshotted (SQLite opened in &lt;code&gt;mode=ro&amp;amp;immutable=1&lt;/code&gt;) and never written to;
everything derived lives in a separate owner-only vault, and the code repository holds no
data. The meaning graph is built on the atoms library&amp;rsquo;s knowledge-base module: an
append-only, schema-validated JSONL event log folded into a disposable SQLite index.&lt;/p&gt;
&lt;p&gt;The schema itself is data, verified mechanically: &lt;strong&gt;27 node types and 50 predicates&lt;/strong&gt;,
&lt;strong&gt;9 provenance origins in 6 ranks&lt;/strong&gt;, &lt;strong&gt;31 locator kinds&lt;/strong&gt; tying every claim to its source element,
the 53-emotion vocabulary, &lt;strong&gt;17 inference rules&lt;/strong&gt;, and &lt;strong&gt;42 sources&lt;/strong&gt; behind the 929
defined dimensions (610 native, 126 vendor-computed, 86 aggregates, 74 deterministic
measures, 29 model interpretations, 4 structural).&lt;/p&gt;
&lt;h2 id="security-model"&gt;&lt;a href="#security-model" class="header-anchor"&gt;&lt;/a&gt;Security model
&lt;/h2&gt;&lt;p&gt;Source content is assumed adversarial (prompt injection in a message or mail), and the
model may hallucinate or misuse tools. Defences are structural:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;No ambient capabilities.&lt;/strong&gt; The agent framework (Hermes Agent) has 26 built-in
toolsets disabled (terminal, files, code execution, web, browser, delegation, memory,
cloud speech…); no cloud provider, update check or external login; the only model
endpoint is a loopback Ollama server.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;One narrow interface.&lt;/strong&gt; Data is reachable only through a local MCP server over stdio
(41 read-only or propose-only tools, 20 exposed to the agent), with closed schemas, validated arguments, explicit truncation and a content-free access
log. Tools can &lt;em&gt;propose&lt;/em&gt;, never &lt;em&gt;decide&lt;/em&gt;.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Privilege separation and pseudonymisation.&lt;/strong&gt; Only ingestion holds full-disk access;
analysis has no network. Third parties are opaque codes, and a real name in an
identifier is rejected by the schema.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Sensitivity levels&lt;/strong&gt; (0–3) per element with a lower ceiling for remote sessions;
remote access only through a NetBird VPN, TOTP and strict session cookies.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Ethical exclusions&lt;/strong&gt;: vendor-inferred ethnicity, skin tone and gender are never read.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="models"&gt;&lt;a href="#models" class="header-anchor"&gt;&lt;/a&gt;Models
&lt;/h2&gt;&lt;p&gt;All inference is local; one large model is loaded at a time under a shared GPU lock.&lt;/p&gt;
&lt;table&gt;
	&lt;thead&gt;
			&lt;tr&gt;
					&lt;th&gt;task&lt;/th&gt;
					&lt;th&gt;model&lt;/th&gt;
					&lt;th&gt;runtime&lt;/th&gt;
			&lt;/tr&gt;
	&lt;/thead&gt;
	&lt;tbody&gt;
			&lt;tr&gt;
					&lt;td&gt;agent (tool use, ≥ 64k context)&lt;/td&gt;
					&lt;td&gt;gpt-oss:20b, qwen3:8b fallback&lt;/td&gt;
					&lt;td&gt;Ollama&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;text emotions, voice-transcript emotions&lt;/td&gt;
					&lt;td&gt;Qwen3-30B-A3B-Instruct-2507 (Q4)&lt;/td&gt;
					&lt;td&gt;Ollama&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;text / image embeddings&lt;/td&gt;
					&lt;td&gt;bge-m3 (installed, not yet used) · SigLIP so400m&lt;/td&gt;
					&lt;td&gt;Ollama · PyTorch MPS&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;image reading&lt;/td&gt;
					&lt;td&gt;qwen3-vl:8b (installed, not yet used)&lt;/td&gt;
					&lt;td&gt;Ollama&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;speech-to-text&lt;/td&gt;
					&lt;td&gt;Whisper large-v3-turbo&lt;/td&gt;
					&lt;td&gt;MLX&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;voice emotion (5 layers)&lt;/td&gt;
					&lt;td&gt;wav2vec2 dimensional · emotion2vec+ · AST · openSMILE eGeMAPS · Qwen2.5-Omni-7B&lt;/td&gt;
					&lt;td&gt;PyTorch MPS · CPU · llama.cpp (Metal)&lt;/td&gt;
			&lt;/tr&gt;
	&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;Most models (12) are smoke-tested on synthetic data only (a fictitious French sentence
synthesised by a local TTS, then passed through the whole audio chain).&lt;/p&gt;
&lt;h2 id="evaluation--results"&gt;&lt;a href="#evaluation--results" class="header-anchor"&gt;&lt;/a&gt;Evaluation &amp;amp; results
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Agent answer quality.&lt;/strong&gt; A 16-question set (2 trap questions, 62 criterion checks),
with ground truth computed by calling the tools directly, scores tool choice, &lt;em&gt;numerical
fidelity&lt;/em&gt; (every number in the answer must appear in that turn&amp;rsquo;s tool outputs),
correctness, trap handling and partial-period flagging: &lt;strong&gt;73 % → 100 % of the 62
criterion checks&lt;/strong&gt; (16 questions, single run), after fixes to tool descriptions,
argument validation, configuration and the scoring rubric, measured on the same set
used to drive the fixes.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Server-side error correction.&lt;/strong&gt; The next day, the same 16-question set fell to 76 %
with the reduced 8-tool interface and recovered to 90 %; 12 cross-source questions went
from 73 % to 90 % (criterion level); 20 deliberately unusual questions scored 89 %
(criterion level, single run) and exposed silent-zero failures, since fixed.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Context and latency.&lt;/strong&gt; Tool descriptions cut from 23.5 k to 9.5 k characters; one
heavy aggregate query from 172 s to 0.1 s (single timing); all heavy benchmark queries
≤ 0.3 s.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Cross-exploration scenarios.&lt;/strong&gt; 61 scenarios, written as templates resolved
automatically on the real data: the oracle code computing each ground truth runs 61/61,
with no leak at remote sensitivity ceilings 1 and 2; the agent itself has not yet been
scored on them.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Verification.&lt;/strong&gt; 56 named schema checks green; 631 source columns confirmed against
inventoried database schemas; 1,281 Python tests, 16 JavaScript test files and 110
quality tests on real data that report counts only (as of 17 Oct 2026).&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="limitations--next-steps"&gt;&lt;a href="#limitations--next-steps" class="header-anchor"&gt;&lt;/a&gt;Limitations &amp;amp; next steps
&lt;/h2&gt;&lt;p&gt;Evaluation sets are small and authored by the system&amp;rsquo;s designer; they measure fidelity
and regressions rather than general capability. Emotion outputs are hypotheses: the
valence/arousal coordinates of the vocabulary are starting values, and personal
calibration of voice emotion from validated examples is still pending, as is the larger
target agent model. Agent answers take tens of seconds on a 20B model.&lt;/p&gt;
&lt;h2 id="stack"&gt;&lt;a href="#stack" class="header-anchor"&gt;&lt;/a&gt;Stack
&lt;/h2&gt;&lt;p&gt;&lt;code&gt;Python&lt;/code&gt; · &lt;code&gt;SQLite / FTS5&lt;/code&gt; · &lt;code&gt;Ollama&lt;/code&gt; · &lt;code&gt;llama.cpp (Metal)&lt;/code&gt; · &lt;code&gt;MLX&lt;/code&gt; · &lt;code&gt;PyTorch MPS&lt;/code&gt; · &lt;code&gt;Hermes Agent&lt;/code&gt; · &lt;code&gt;MCP&lt;/code&gt; · &lt;code&gt;SigLIP&lt;/code&gt; · &lt;code&gt;Whisper&lt;/code&gt; · &lt;code&gt;emotion2vec&lt;/code&gt; · &lt;code&gt;openSMILE&lt;/code&gt; · &lt;code&gt;NetBird&lt;/code&gt; · &lt;code&gt;PWA&lt;/code&gt; · &lt;code&gt;launchd&lt;/code&gt;&lt;/p&gt;</description></item></channel></rss>