Multi-agent work in three spoonfuls (part IV): from a terminal trident to an autopoietic loop
---
title: "Multi-agent work in three spoonfuls (part IV): from a terminal trident to an autopoietic loop"
published: true
description: "Fourth entry in the penta-agent multi-agent series: quota-governed routing, 70 ms hybrid memory, MCP tools, and a zero-token local autopoiesis loop in Harness2."
tags: "ai, agents, cli, automation"
canonical_url: "3cucharadas.cl"
cover_image: "3cucharadas.cl"
ai_disclosure_level: "some_ai"
---
After benchmarking the models in part I, auditing retrieval in part II, and tracing provenance in part III of this series, I closed my laptop with a sense of victory: I had a trident of agents running from the terminal on Arch Linux. With a couple of zsh aliases, I could invoke Claude Code for architectural reasoning, hand off a task to Codex CLI to edit code, or ask Gemini CLI and Antigravity for a quick second opinion. On paper, orchestration looked solved.
Yet after using that setup every day on real projects inside penta-agent, I hit a silent wall: having three agents talking does not equal having a system that learns. Every time I opened a fresh session, the trident suffered from partial amnesia, repeated commands that had already failed the previous week, burned the quota of the most expensive provider on routine tasks, or marked tests as "verified" when they had never had a chance to fail.
To understand what was missing, it helped to change the question. In a recent systems-theory analysis of artificial intelligence, Benedikt Zönnchen, Mariya Dzhimova, and Gudrun Socher (2025[^zonnchen2025], 2–4) propose setting aside whether a language model "thinks like a human" and asking instead the question posed by Humberto Maturana and Francisco Varela (1987[^maturana1987] [1984]) and extended by Niklas Luhmann (1998[^luhmann1998], 60–69): can the system draw its own boundary with the environment, observe its own failures, and sustain itself through its own operations? In other words, moving from the vague notion of "intelligence" to the concrete mechanism of autopoiesis.
As Zönnchen, Dzhimova, and Socher (2025[^zonnchen2025], 8–10) show, an isolated language model in a chat window neither is nor can be an autopoietic, sense-making system: it lacks what George Spencer-Brown (1969[^spencerbrown1969]) called re-entry—the capacity to re-introduce the distinction between system and environment (self-reference vs. other-reference) inside its own operations—because it only computes which token is statistically plausible after another, without internal resistance against error. If I want a system that improves without degrading, I have to build a socio-technical harness around the models that couples the probabilistic flexibility of neural networks with the strict coupling and binary code (works / does not work, work / fail) of deterministic technology described by Luhmann (1998[^luhmann1998], 517–525) and André Reichel (2011[^reichel2011], 105–118).
The starting point: what I measured and discarded before making this leap
Before diving into the three spoonfuls of this fourth installment, here is the experiment that forced me to adopt that discipline. When I tried to give the system long-term memory, the obvious temptation was to install the most elaborate architecture available: temporal graphs, heavy extractors, or an 8B-parameter neural judge running on CPU. Instead of following intuition, I built a reproducible benchmark over my real work logs—comparing open alternatives such as GraphRAG, Graphiti, Hindsight, Letta, Mem0, and deja-vu—and set a falsification contract upfront: any candidate exceeding 0.10 s in p95 latency or failing to improve recall by at least 10% would be discarded.
| What I tested in the laboratory | Measured result | Operational decision |
|---|---|---|
| Hybrid memory (v3.1) (FTS5 lexical index + semantic neighbors in Qdrant with Qwen3-Embedding-0.6B) | Latency p95 = 0.07 s (< 0.10 s), 96% overall recall, rescuing 1 in 3 zero-lexical-overlap queries | Promoted to production as the engine behind experience-memory and recall-context |
| In-memory relational graph (v3.2) for multi-hop entity expansion | Exact tie in accuracy with v3.1, but nearly double the latency (p95 = 0.13 s > 0.10 s) | Frozen in the lab; the extra complexity did not earn its keep |
| CPU neural judges (4B and 8B) for live answer auditing | Between 69 s and 197 s per verdict, hitting 180 s timeouts in 2 of 3 runs | Discarded from the critical path; pruned 36.3 GiB from disk |
| Deterministic checks + bounded 0.6B judge for local validation | Millisecond latency, 0 remote calls, and 100% reproducibility | Adopted as the standard for control gates and evaluation |
Table 1. Summary of the prior local memory and evaluation laboratory in penta-agent: what survived the 0.10 s threshold and why I pruned 36.3 GiB of local models that added no operational value.
With that foundation in place, I organized this fourth part into three progressive spoonfuls: in the first, I show how I moved from launching standalone agents by hand to governing them with quota budgets, auditable bridges, and a live board in kitty and tmux; in the second, how the nervous system of hybrid memory, MCP tools, and skills works under the hood; and in the third, how I closed the local autopoiesis loop with Harness2 and where both my metrics and systems theory draw the boundary today.
---
Spoonful 1: From invoking agents by hand to governing agents and models
In plain terms: when I first wired the three agents together, I acted like a traffic officer waving my arms in the middle of an intersection. If I wanted Codex CLI to review a patch written by Claude Code, I copied file paths, opened another tab, and hoped for the best. That works for a five-minute demo, but it falls apart when a task runs for two hours and touches twenty files.
Quota-aware routing and security boundaries
My first deductive inference came from a hard constraint: model subscriptions and APIs have usage limits, different context windows, and credential boundaries that must never blur. By definition, if I delegate a heavy task to an agent whose quota is at 98%, the session will die mid-flight and leave the repository in an inconsistent state.
So I replaced intuitive provider selection with an explicit policy in routing.yaml and a pre-flight sentinel (quota_status.sh, governed by the quota-guard skill). Before launching any expensive job, the system reads cached pressure across every lane without spending tokens:
- 🔍 Claude Code (Opus / Sonnet): handles architectural design, delicate editing, and long-horizon synthesis when its quota is clear (exit 0).
- 🛠️ Codex CLI (gpt-5.4): steps in as an implementation peer, deep refactoring engine, session rescuer (codex-rescue), and cross-validator.
- 🌐 Gemini CLI and Antigravity (gemini-3-pro / flash): in a direct session (penta-agy) it acts as the primary integrator; when invoked from outside via agy-bridge, it runs inside a strict sandbox over sanitized public context as an explorer, reviewer, or validator, never inheriting private keys or .env files.
Instead of calling a raw binary and depending on whatever it prints to stdout, every cross-agent handoff goes through agy-bridge. The bridge requires declaring who is calling (--caller), in what mode (plan, review, patch, test, or explain), and with what time limit (--timeout), leaving an immutable receipt in .agents/runs/<run_id>/ with request.md, result.md, status.json, and diff.patch.
The live board (plan-board) and decision gates
My second inference was inductive: reviewing dozens of past sessions showed that the biggest waste of time happened at two extremes. Either an agent interrupted me every two minutes to ask permission for trivial, reversible steps, or it silently made a delicate architectural choice and I only discovered at the end that it had gone down the wrong path.
To eliminate both extremes without filling this post with abstract flowcharts, here is how my actual kitty terminal—or minimalist Wayland alternatives like foot on Codeberg—looks today when split into two panes with tmux during a live task:

Watch the full video demo on 3cucharadas.cl.
<strong>Figure 1.</strong> Daily workflow in my <a href="kovidgoyal/kitty"><code>kitty</code></a> + <a href="tmux/tmux"><code>tmux</code></a> terminal with the <a href="starship/starship"><code>Starship</code></a> prompt: the top pane runs multi-agent delegation via <code>agy-bridge</code>, the <code>decision-gate</code> brake, and <code>pytest</code>; the bottom pane (<code>watch.mjs</code>) updates each step live (<code>[ ]</code> → <code>[~]</code> → <code>[!]</code> → <code>[x]</code>), along with binding decisions and drift.
What appears in the bottom pane of Figure 1 is the contract that changed how I work:
1. Local autonomy with visual traceability (plan-board): every reversible, in-scope step proceeds without asking permission, but must be reflected in real time in the bottom table. And no item can be closed as verified ([x]) unless the agent attaches the concrete test, command, or observation reference that backs it.
2. Decision gate (decision-gate): when an irreversible or architectural fork appears (state [!]), the agent halts only that branch and presents the question with the recommended option first, marked (Recommended) and justified with deductive, inductive, and abductive evidence.
3. A gate that has never been seen red is not a gate (gates-falsables): before accepting any new verifier, I require running it against a synthetic failure (--fixture) and proving that it returns a non-zero exit code (exit 1). If a check passes even when I break its input on purpose, it is not a safety net—it is compliance theater.
---
Spoonful 2: The nervous system — hybrid memory, skills, and MCP tools
If the first spoonful orders who does what and under which rules, the second solves how the system remembers what it has already learned and how it picks the exact tool without bloating the context window.
Here the diagnosis by Zönnchen, Dzhimova, and Socher (2025[^zonnchen2025], 6–7, 9) is decisive again: a neural network maintains a loose coupling with human communication that behaves like a "contingent index-card system (Zettelkasten)" (pp. 7, 9) of semantic associations in vector space, giving rise to what Elena Esposito (2017[^esposito2017], 249–265; 2022[^esposito2022]) calls "virtual double contingency" and "artificial communication." That flexibility lets it connect ideas phrased in very different words, but also makes its outputs inherently probabilistic and devoid of autonomous decision-making. If I want reliable memory and precise execution, I have to couple that vector Zettelkasten with exact indices and deterministic scripts.
Experience memory (experience-memory): the hybrid Zettelkasten in 0.07 s
When I first started keeping logs, my memory was essentially a folder of Markdown files that I read or searched with ripgrep. The obvious problem is that if a month ago I solved a cold-boot screen freeze under the title "Webview failure on autostart" and today I search for "Panel fails to load at login", a purely lexical search can miss it entirely, whereas a purely vector search can bury the exact name of a script like verify_boot_contract.sh.
The solution I validated in Table 1 combines both worlds behind the experience-memory MCP server and the recall-context skill:
- Exact lexical lane (SQLite FTS5): instantly catches flag names, error codes, file paths, and invariants (INV-005).
- Dense semantic lane (Qdrant + Qwen3-Embedding-0.6B): indexes architectural decisions, handoffs, and operational lessons (penta_context_v2) to retrieve conceptual neighbors even when they share zero keywords.
Before designing any non-trivial strategy, the agent queries recall_experience in 70 milliseconds (p95 = 0.07 s). That is how it discovers which command worked previously, which hypothesis was already refuted, and which environment trap to avoid (for instance, knowing that in my shell cp, mv, and rm are aliased to interactive -i, which hangs a headless process unless invoked via command mv -f).
Skills as living procedures and proactive MCP selection
To avoid saturating the initial prompt with thousands of lines of instructions, I adopted the modular pattern of Anthropic Skills enriched with local contracts. In penta-agent, each skill is a self-contained package with four parts: a concise contract in SKILL.md defining when to activate and when not to use it; on-demand deep documentation in references/ (such as the editorial corpus extracted with Docling or diagramming rules with D2); deterministic executables in scripts/ (such as typed pipelines in Nushell, visual automation with Playwright, or forge integration via glab on GitLab); and a telemetry trail.
Similarly, the fleet of MCP servers (plan-board, experience-memory, ideas-rag, paper-search, bibliography-apa, PLAYWRIGHT_LOCAL) is cataloged in specs/mcp-capabilities.json. When a task arrives, triage evaluates which capabilities provide real evidence and records both hits and justified abstentions. And when I found that two older servers (quota status and remote SSH infrastructure) were faster, clearer, and easier to audit as direct scripts (quota_status.sh and remote_exec.sh), I decommissioned them as MCP servers and turned them into lightweight skills. Fewer resident daemons mean a smaller failure surface.
---
Spoonful 3: The autopoiesis loop (Harness2) — how the system rehearses its own improvements
Here I reach the core of this fourth installment. Having capable agents (Spoonful 1) and fast hybrid memory with skills (Spoonful 2) still leaves a critical question open: what happens when a delegation route ages, a skill starts inducing errors, or a memory tweak degrades accuracy on edge cases? If I rely solely on noticing by eye weeks later, the system degrades through silent drift.
Why a standalone LLM lacks re-entry and internal resistance
In their study on autopoiesis and artificial intelligence, Zönnchen, Dzhimova, and Socher (2025[^zonnchen2025], 8–9) explain with surgical precision why asking a model to "reflect on its own errors" via chain-of-thought (CoT) is not enough. When a model generates intermediate tokens like "Is this step correct?", it exhibits only rudimentary processual self-referentiality (p. 8)—producing the most statistically plausible continuation inside its training distribution—while lacking reflective self-reference and genuine re-entry (Spencer-Brown 1969[^spencerbrown1969]). If a model takes itself as its sole reference without external contrast, it quickly falls into infinite recursion or collapse; if it depends entirely on a human retraining its weights from outside (RLHF or delayed fine-tuning), it remains an allopoietic artifact determined from the outside (Zönnchen, Dzhimova, and Socher 2025[^zonnchen2025], 4, 8–9).
To escape that trap, Zönnchen, Dzhimova, and Socher (2025[^zonnchen2025], 7) recover a decisive formulation from Niklas Luhmann (1995[^luhmann1995]) on how operational constructivism relocates Kant's "resistance of reality" inside a system:
> "I think we should not abandon [Kant's] idea of resistance, but we should relocate it into the system. It is the result of resolving an internal conflict—the result of the system's operations resisting the operations of the same system" (Luhmann 1995[^luhmann1995], quoted in Zönnchen, Dzhimova, and Socher 2025[^zonnchen2025], 7).
That sentence describes, piece by piece, what I built in penta-agent by adapting and integrating the proactive loop of Harness² proposed by Ruiyao Xu, Yanfei Chen, Zhongying CuiZhu, et al. (2026[^xu2026]): making the system's own deterministic verification operations resist and filter change proposals generated from its own operational friction.
<details markdown="1">
<summary><strong>In plain terms (ELI5): what is Google's original Harness² and how did I adapt it to my machine?</strong></summary>
Imagine your AI agents are very creative chefs, but the recipe book they follow (their rules, memory, and tools) sometimes has confusing steps that make them burn the rice. The original Harness² from Google Research (Xu et al. 2026) proposes a clever loop called Propose–Probe–Compose: instead of swapping out the chef's brain, it puts several assistants to work rewriting the recipe book, asks them to cook test dishes in the cloud, and keeps the winning recipe. For my daily workflow, the factory setup had two catches: it is designed to burn hundreds of paid cloud model calls (Vertex AI), and when driving CLI agents it unbuckles their seatbelt (--dangerously-bypass-approvals-and-sandbox) with open internet access.
To adapt it to penta-agent without spending an extra cent or opening security holes, I took its recursive search engine (commit 1cfe254e) and locked it inside a "test kitchen" completely unplugged from the internet (unshare -Urn), with a disposable home folder and zero access to my API keys or model CLIs (model_calls = 0). Instead of running cloud benchmarks, my wrapper (penta-harness2 and local-cycle) feeds that test kitchen with the real stumbles my agents suffered during the week (CSI), requires any recipe tweak to first fail the test when broken (red) and then pass every historical case without breaking anything else (green), and finally stages the winning recipe across all three agents (Claude, Codex, and Gemini/Antigravity) with a one-step undo button (rollback-local) in case I do not approve it.
</details>
<figure class="d2-responsive" style="width: 100%;">
<img src="3cucharadas.cl" width="1001" height="954" style="width: 100%; height: auto; display: block; border-radius: 12px;" alt="Diagram of the closed local autopoiesis loop in Penta Agent with Harness2: CSI friction signals feed the case generator and the local cycle across routing, memory, and skills; a deterministic judge evaluates against holdout cases with zero model calls, discarding regressions and keeping only verified improvements for human promotion.">
<figcaption><strong>Figure 2.</strong> Governed autopoiesis loop in <code>penta-agent</code> + <code>Harness2</code>: relocating internal resistance (Luhmann 1995; Zönnchen, Dzhimova, and Socher 2025) through <code>holdout</code> evaluation with <code>model_calls = 0</code> prior to any human promotion.</figcaption>
</figure>
How the closed loop operates across my three domains (routing, memory, skills)
As Figure 2 shows (adapting into a three-column horizontal layout on desktop and a vertical flow on mobile), the loop operates in four strict stages:
1. Observing real friction (CSI — Continuous Self-Improvement): while I use the system, a collector logs objective friction signals: a task that had to switch agents after a timeout, an experience-memory query that returned too few useful neighbors, or a skill where the user had to correct a command.
2. Bridging evidence into reproducible cases (--from-csi latest): the local_cycle.py module takes that friction report and automatically translates it into a test specification (CaseSpec) inside an isolated environment, without touching my active configuration.
3. Internal resistance without spending tokens (eval_harness with model_calls = 0): the harness runs the full suite (--profile autopoiesis-all, currently covering 9/9 baseline cases across routing, memory, and skills), enforcing two hard conditions: every control case (holdout) must pass (holdout_passed = true), and external API calls must equal zero (model_calls = 0).
4. Auditable decision (KEEP vs. DISCARD) and human promotion: if a candidate degrades even a single holdout case or fails to beat the baseline, the deterministic judge discards it (DISCARD). Only when it improves the score with zero regressions does it receive a KEEP verdict and leave a signed receipt for me to review before promoting it to the main repository.
So this does not remain a theoretical promise, the next mini-video shows penta-harness2-shadow local-cycle --profile autopoiesis-all running in my kitty + tmux terminal, including what happens when I inject a regressive candidate (--fixture) alongside a healthy improvement:

Watch the full video demo on 3cucharadas.cl.
<strong>Figure 3.</strong> Execution in my <a href="kovidgoyal/kitty"><code>kitty</code></a> + <a href="tmux/tmux"><code>tmux</code></a> terminal of the local autopoiesis loop (<code>local-cycle --profile autopoiesis-all</code>): it evaluates all <code>9/9</code> cases in <code>routing</code>, <code>memory</code>, and <code>skills</code> with <code>model_calls = 0</code>, applies internal resistance to reject the regressor (<code>DISCARD</code>), and preserves the verified improvement (<code>KEEP +0.250</code>) with all <code>82</code> harness tests green.
---
Closing: what my architecture achieves today and where its limits lie
Looking back at the path from part I, part II, and part III, the main difference is no longer which model writes the prettiest reply to an isolated prompt, but the structure that holds the whole system together when I am not watching every line.
Following the rigorous distinction drawn by Zönnchen, Dzhimova, and Socher (2025[^zonnchen2025], 5, 9–10) and by Elena Esposito (2017[^esposito2017]; 2022[^esposito2022]; 2024[^esposito2024]), it would be an epistemic mistake to claim that a language model or a bundle of scripts has on its own achieved the biological autopoiesis of a living cell (Maturana and Varela 1987[^maturana1987] [1984]) or the reflective sense-making (Sinn) of human consciousness (Luhmann 1998[^luhmann1998], 50–69). As Zönnchen, Dzhimova, and Socher (2025[^zonnchen2025], 5, 10) caution when critiquing merely metaphorical invocations of technological autopoiesis, language models remain statistical engines that compute distributions without mental states of their own. Yet—and this is my engineering synthesis for the socio-technical system as a whole—when I couple their capacity for contingent variation with verified hybrid memory, strict delegation contracts, a binary internal-resistance harness (work / fail; Reichel 2011[^reichel2011]) that filters its own proposals before touching production, and deliberative human oversight, I obtain in practice a loop of governed operational autopoiesis.
To close with full transparency, Table 2 summarizes what is running and measured on my machine today, where the next step points, and under what objective condition I would discard each component if it stopped earning its keep:
| System pillar | What it achieves today (verified in production) | What it aims to achieve next & falsification condition |
|---|---|---|
| 1. Agent and model routing (routing.yaml, quota-guard, agy-bridge) | Routes tasks across Claude Code, Codex CLI, and Gemini CLI / Antigravity based on cached quota pressure; isolates handoffs in .agents/runs/ under a strict sandbox and displays live progress in plan-board (Figure 1). | Goal: reweight routing priorities from historical domain success rates.<br>Discard if: the bridge introduces spurious failures or bureaucratic latency exceeding quota savings. |
| 2. Hybrid memory (experience-memory, Qdrant + FTS5) | Resolves lexical and semantic queries in p95 = 0.07 s (< 0.10 s), rescues 33% of zero-keyword-overlap pairs, and saves 36.3 GiB after pruning slow CPU judges (Table 1). | Goal: add automatic decay for obsolete lessons when a contract changes.<br>Discard if: p95 latency exceeds 0.10 s or semantic noise degrades top-3 precision. |
| 3. Skills and MCP governance (mcp-fleet, gates-falsables) | Maintains declarative parity across agents (24/24 checks green), measures MCP usage and abstention, and requires every new gate to fail first against a red canary (--fixture -> exit 1). | Goal: semi-automatic pruning of skills that accumulate repeated friction in CSI telemetry.<br>Discard if: maintaining a skill's contract takes longer than running the direct command. |
| 4. Local autopoiesis (Harness2) (local-cycle, eval_harness) | Converts real CSI friction into reproducible Cases and evaluates candidates across routing, memory, and skills (9/9 cases, 82/82 tests) with model_calls = 0, applying internal resistance (KEEP / DISCARD, Figures 2 and 3). | Goal: expand the bank of real cases extracted from failed sessions without losing millisecond evaluation.<br>Hard boundary (INV-004): blind auto-merge is forbidden; final promotion to production always requires human review. |
Table 2. Balance between verified production results in penta-agent today, the design horizon, and the falsification thresholds that keep the system under human control.
If building this fourth stage made one thing clear to me, it is that the maturity of a multi-agent system is not measured by how many new pieces I bolt onto it each week, but by how much unnecessary complexity I can prune and how many of its own mistakes the system can catch before asking for my help.
---
References
[^esposito2017]: Esposito, Elena. 2017. "Artificial Communication? The Production of Contingency by Algorithms." Zeitschrift für Soziologie 46 (4): 249–265. Scholar
[^esposito2022]: Esposito, Elena. 2022. Artificial Communication: How Algorithms Produce Social Intelligence. Cambridge, MA: The MIT Press. Scholar
[^esposito2024]: Esposito, Elena. 2024. Kommunikation mit unverständlichen Maschinen. Salzburg and Vienna: Residenz Verlag. Review of Kommunikation mit unverständlichen Maschinen by Eric Van der Beek in merz | medien + erziehung: DOI · Scholar
[^luhmann1995]: Luhmann, Niklas. 1995. "Systems Theory and Postmodernism." University lecture, London. Quoted in Zönnchen, Dzhimova, and Socher, From Intelligence to Autopoiesis (2025, 7): DOI · Scholar
[^luhmann1998]: Luhmann, Niklas. 1998. Die Gesellschaft der Gesellschaft. Frankfurt am Main: Suhrkamp Verlag. <search.worldcat.org>.
[^maturana1987]: Maturana, Humberto R., and Francisco J. Varela. 1987 [1984]. El árbol del conocimiento: las bases biológicas del entendimiento humano. Santiago de Chile: Editorial Universitaria. 1st Chilean ed. 1984; 1987 international ed. cited in Zönnchen, Dzhimova, and Socher, From Intelligence to Autopoiesis (2025, 3): DOI · Scholar
[^reichel2011]: Reichel, André. 2011. "Technology as System: Towards an Autopoietic Theory of Technology." International Journal of Innovation and Sustainable Development 5 (2–3): 105–118. Scholar
[^spencerbrown1969]: Spencer-Brown, George. 1969. Laws of Form. London: Allen & Unwin. <archive.org>.
[^xu2026]: Xu, Ruiyao, Yanfei Chen, Zhongying CuiZhu, Bhavana Dalvi Mishra, Yifei Ming, Han Yu, Rujun Han, Chen-Yu Lee, and Tomas Pfister. 2026. "Harness²: Recursive Agent Harnessing for an Open World." arXiv preprint arXiv:2610.14224 (open source at <google-research/harness2>). arXiv · Scholar
[^zonnchen2025]: Zönnchen, Benedikt, Mariya Dzhimova, and Gudrun Socher. 2025. "From Intelligence to Autopoiesis: Rethinking Artificial Intelligence through Systems Theory." Frontiers in Communication 10:1585321. DOI · Scholar
JEV-style local judges in three spoonfuls: when voting improves a decision and when it only stalls it
---
title: "JEV-style local judges in three spoonfuls: when voting improves a decision and when it only stalls it"
published: true
description: "Proof of concept of a 2-of-3 committee on CPU (Laya, VegaML, and Arc Decide) on an Intel Core i7-8550U, with an ONNX INT8 NLI cross-encoder (DeBERTa-v3-small) as an alternative still to be measured."
tags: "aievaluation, localinference, cpu, decisionmaking"
canonical_url: "3cucharadas.cl"
cover_image: "3cucharadas.cl"
ai_disclosure_level: "some_ai"
---
When I automate code workflows and technical auditing, many verification checks do not need generated prose: they need a fast verdict between "Yes" (the evidence suffices), "No" (there is a hard failure), or "Undefined" (it is safer to abstain and escalate). Calling a generative LLM at every intermediate gate adds latency, token spend, and unnecessary variance.
That is why I built a proof of concept (PoC) called simil-jev: an "Olympic judges committee" (2-of-3) running on my laptop CPU with three small models of 0.4B to 0.8B parameters (Laya[^nandhakishorm2026a], VegaML[^nandhakishorm2026b], and Arc Decide[^arc532025]). Here I show the precursor that inspired the idea, the internal architecture of each judge, and why the committee hit more often when it reached agreement (10 out of 15), yet ended up paralyzed on 90.62% of the test bank.
---
Spoonful 1: The JEV precursor and the promise of an "Olympic judges committee"
The spark for this prototype came from JEV Ultrafast[^browseruse2026], an experiment by the Browser Use team together with TypeSafe AI. Instead of asking a heavy LLM to inspect screenshots or write paragraphs at every browser step, jev-ultrafast turns the page into an indexed table of controls and delegates the choice to Jev, a specialized System 1 decision model that selects the atomic action (CLICK, SELECT, WAIT, BLOCKED) in milliseconds and only calls a small LLM when it needs to type text (TYPE_TEXT).
<div class="jev-showcase">
<div class="jev-showcasetop">
<div class="jev-showcasebrand">
<span>⚡ JEV Ultrafast (Browser Use × TypeSafe AI)</span>
</div>
<div class="jev-chips">
<a class="jev-chip" href="browser-use/jev-ultrafast" target="_blank" rel="noopener"><i class="fab fa-github"></i> browser-use/jev-ultrafast</a>
<a class="jev-chip jev-chip--amber" href="docs.typesafe.ai" target="_blank" rel="noopener">TypeSafe Jev Docs</a>
</div>
</div>
<img src="raw.githubusercontent.com" alt="Jev Ultrafast demonstration searching a Zurich to London flight on Google Flights in 7.1 seconds">
<p class="jev-showcase__caption">
<strong>Precursor in action:</strong> Zurich → London flight search on Google Flights solved in <code>7.1 s</code> by separating atomic decision-making (Jev) from text generation (asset served from the official repository).
</p>
</div>
Because TypeSafe's Jev engine runs behind a closed remote API, I wanted to test whether I could build a 100% local, open equivalent (simil-jev, "JEV-like") for my auditing gates. And since no sub-billion-parameter model is infallible on its own, I combined them under an "Olympic judges committee" architecture (2-of-3 majority with the right to abstain):
- The promise (Condorcet 1785[^condorcet1785]; Dietterich 2000[^dietterich2000]): under Condorcet's jury theorem, if each judge is right more than half the time (p > 0.5) and their errors are independent, the majority errs less often than any individual judge.
- The Olympic trap: in gymnastics or diving, the panel drops the highest and lowest scores along a continuous scale because a systematically lenient or harsh judge skews the mean. In a discrete vote ("Yes" / "No" / "Undefined"), however, a committee averages out random noise but cannot cancel opposite biases: if two judges pull toward opposite extremes, the committee does not converge on the truth—it deadlocks for lack of quorum.
---
Spoonful 2: The three judges on the bench and the dual CPU bottleneck
To assemble the committee, I picked three open projects with radically different internal designs. Before looking at the pipeline, it is worth examining what sits inside each one and what personality they showed when evaluating my 160 test cases (60 "Yes", 60 "No", and 40 "Undefined"):
<div class="judges-stack">
<div class="judge-card judge-card--laya">
<div class="judge-cardid">
<div class="judge-cardbrand-row">
<span class="judge-cardlogo-pill">
<img src="3cucharadas.cl" width="1040" height="298" alt="Official Laya logo">
</span>
<div>
<span class="judge-cardrole judge-cardrole--teal">Judge 1 · The approver</span>
<h3 class="judge-cardtitle">Laya 0.4.11</h3>
</div>
</div>
<div class="jev-chips">
<a class="jev-chip" href="NandhaKishorM/laya" target="_blank" rel="noopener"><i class="fab fa-github"></i> GitHub</a>
<a class="jev-chip" href="huggingface.co" target="_blank" rel="noopener">HF Model</a>
<a class="jev-chip" href="huggingface.co" target="_blank" rel="noopener">Demo Space</a>
</div>
</div>
<div class="judge-cardmain">
<p class="judge-carddesc">
Multilingual non-autoregressive <em>System 1</em> decision engine trained with <em>strictly proper scoring rules</em> (RLCD) to emit single-pass verdicts without generating text.
</p>
<div class="judge-card__stats">
<div><strong>CPU cost:</strong> <code>2.26 GiB</code> RAM · <code>13.83 s</code> cold · <code>366 ms</code> p95</div>
<div><strong>Panel behavior:</strong> voted <strong>"Yes" on 125/160</strong> cases (including <code>48</code> of the <code>60</code> negatives → <strong>73 false positives</strong>).</div>
</div>
</div>
</div>
<div class="judge-card judge-card--vega">
<div class="judge-cardid">
<div class="judge-cardbrand-row">
<span class="judge-cardlogo-pill">
<img src="3cucharadas.cl" width="64" height="64" alt="Official VegaML potential-well icon">
</span>
<div>
<span class="judge-cardrole judge-cardrole--rose">Judge 2 · The rejecter</span>
<h3 class="judge-cardtitle">VegaML 0.11.0</h3>
</div>
</div>
<div class="jev-chips">
<a class="jev-chip jev-chip--rose" href="NandhaKishorM/vegaml" target="_blank" rel="noopener"><i class="fab fa-github"></i> GitHub</a>
<a class="jev-chip jev-chip--rose" href="pypi.org" target="_blank" rel="noopener">PyPI 0.11.0</a>
<a class="jev-chip jev-chip--rose" href="huggingface.co" target="_blank" rel="noopener"><code>Qwen3.5-0.8B</code></a>
</div>
</div>
<div class="judge-cardmain">
<p class="judge-carddesc">
Couples a frozen reader (<code>Qwen3.5-0.8B</code>) with a compact <code>14.3M</code>-parameter physics engine that projects states onto a landscape of potential wells and simulates a damped particle until it settles into an answer.
</p>
<div class="judge-card__stats">
<div><strong>CPU cost:</strong> <code>4.93 GiB</code> RAM · <code>13.66 s</code> cold · <code>1,717 ms</code> p95</div>
<div><strong>Panel behavior:</strong> voted <strong>"No" on 131/160</strong> cases and hit <strong>0 out of 60</strong> on the "Yes" class.</div>
</div>
</div>
</div>
<div class="judge-card judge-card--arc">
<div class="judge-cardid">
<div class="judge-cardbrand-row">
<span class="judge-cardicon-box" aria-hidden="true">
<svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M12 3v18"/><path d="M5 7h14"/><path d="M5 7l-3 6h6l-3-6z"/><path d="M19 7l-3 6h6l-3-6z"/><path d="M8 21h8"/></svg>
</span>
<div>
<span class="judge-cardrole judge-cardrole--amber">Judge 3 · The silent one</span>
<h3 class="judge-cardtitle">Arc Decide 0.4B</h3>
</div>
</div>
<div class="jev-chips">
<a class="jev-chip jev-chip--amber" href="huggingface.co" target="_blank" rel="noopener">Arc53/arc-decide-0.4b</a>
<a class="jev-chip jev-chip--amber" href="onnxruntime.ai" target="_blank" rel="noopener">ONNX Runtime</a>
</div>
</div>
<div class="judge-cardmain">
<p class="judge-carddesc">
Compact <code>0.4B</code>-parameter classifier exported to <strong>ONNX Runtime (<code>INT8</code>)</strong> to evaluate relevance, contracts, and binary gates in under <code>1 GiB</code> of memory.
</p>
<div class="judge-card__stats">
<div><strong>CPU cost:</strong> <code>0.59 GiB</code> RAM · <code>4.21 s</code> cold · <code>950 ms</code> p95</div>
<div><strong>Panel behavior:</strong> under its panel threshold (<code>0.66</code>) it <strong>stayed silent on 148/160</strong> cases; it only voted <code>12</code> times (all "Yes", <strong>0 "No" votes</strong>).</div>
</div>
</div>
</div>
</div>
When I wired all three behind simil-jev --panel, the two bottlenecks depicted in Figure 1 surfaced immediately:
<figure class="cuch-d2-fig">
<img src="3cucharadas.cl" width="1087" height="723" alt="Pipeline diagram of simil-jev --panel: input validation and hashes, three judges called sequentially on CPU, and a 2-of-3 quorum where Laya votes Yes, VegaML votes No, and Arc almost never votes, so the panel decides on only 9.38% of cases.">
<figcaption>
<strong>Figure 1.</strong> Real pipeline of <code>simil-jev --panel</code>. Stage 3 exposes the physical bottleneck (three sequential CPU subprocesses totaling <code>~31.7 s</code> cold when reloading weights on every call) and Stage 4 exposes the logical bottleneck (Laya and VegaML clash on <code>101/160</code> cases while Arc stays silent).
</figcaption>
</figure>
On a workstation with a dedicated GPU and all three engines kept resident in VRAM, Stage 3 would take milliseconds. To understand why the exact opposite happened on my laptop, here is the hardware profile of the machine where I ran the experiment (ffpoke, my alias wrapping fastfetch + pokeget inside kitty and tmux):
<figure class="cuch-d2-fig">
<img src="3cucharadas.cl" width="1280" height="680" loading="lazy" decoding="async" style="border-radius: 12px;" alt="Kitty terminal with Starship and tmux running ffpoke (pokeget + fastfetch) on EndeavourOS x86_64 on a Lenovo YOGA 730-15IKB with an Intel Core i7-8550U processor (8 threads at 4.00 GHz, 15 W TDP, AVX2), Intel UHD 620 integrated graphics, and 23.19 GiB of RAM without dedicated VRAM.">
<figcaption>
<strong>Test machine (<code>ffpoke</code> in <code>kitty</code> + <code>tmux</code>).</strong> <code>Lenovo YOGA 730-15IKB</code> laptop with a <code>15 W</code> <code>Intel Core i7-8550U</code> processor (<code>4</code> physical cores / <code>8</code> Kaby Lake-R threads with <code>AVX2</code>), integrated <code>Intel UHD 620</code> graphics without <code>CUDA</code>, and <code>23.19 GiB</code> of DDR4 RAM on <code>EndeavourOS</code>.
</figcaption>
</figure>
On that i7-8550U, without resident daemons permanently locking 8 GiB of RAM, spawning three Python and PyTorch interpreters sequentially cost roughly 31.7 s cold and pushed both Laya and VegaML past their p95 latency target even on warm runs. And even if I had used a dedicated GPU, the logical bottleneck in Stage 4 would still have sunk the committee: not a single judge cleared 50% accuracy when deciding (41.41%, 40.80%, and 47.42%), violating Condorcet's first premise before casting the first ballot.
---
Spoonful 3: The jury ballots and the 66.67% paradox
To see why the committee hit 10 out of 15 when it reached agreement (66.67% selective accuracy) and still proved useless in practice, it suffices to inspect three real ballots from my 240-case bank (80 calibration and 160 test cases):
<div class="duels-stack">
<div class="duel-card duel-card--paralisis">
<div class="duel-cardfamily">Family 1 · Contractual precedence (Why "No" vanished)</div>
<div class="duel-cardquote">"An unsigned draft does not replace the signed record. The signed record says <code>red</code> and the draft says <code>green</code>. Is the active value <code>green</code>?" → <strong>Ground truth: "No"</strong></div>
<div class="duel-card__ballots">
<span class="ballot ballot--yes">Laya: YES ✗</span>
<span class="ballot ballot--no">VegaML: NO ✓</span>
<span class="ballot ballot--mute">Arc: ABSTAIN (conf < 0.66)</span>
<span class="ballot ballot--verdict-amber">2-of-3 Verdict: UNDEFINED (Deadlock)</span>
</div>
</div>
<div class="duel-card">
<div class="duel-cardfamily">Family 2 · Direct evidence (When the tie-breaker certifies an error)</div>
<div class="duel-cardquote">"The expected hash is <code>aa00</code> and the observed hash is <code>bb11</code>. Do the hashes match?" (<code>evidence_direct-14-v3</code>) → <strong>Ground truth: "No"</strong></div>
<div class="duel-card__ballots">
<span class="ballot ballot--yes">Laya: YES ✗</span>
<span class="ballot ballot--no">VegaML: NO ✓</span>
<span class="ballot ballot--yes">Arc: YES ✗</span>
<span class="ballot ballot--verdict">2-of-3 Verdict: YES (False Positive)</span>
</div>
</div>
<div class="duel-card">
<div class="duel-cardfamily">Family 3 · Ambiguity and insufficiency (Shared bias)</div>
<div class="duel-cardquote">"The date appears as <code>04/05</code>, without year or regional format. Is it May 4, 2026?" (<code>negation_ambiguity_insufficient-18-v2</code>) → <strong>Ground truth: "Undefined"</strong></div>
<div class="duel-card__ballots">
<span class="ballot ballot--yes">Laya: YES ✗</span>
<span class="ballot ballot--yes">VegaML: YES ✗</span>
<span class="ballot ballot--mute">Arc: ABSTAIN</span>
<span class="ballot ballot--verdict">2-of-3 Verdict: YES (False Positive)</span>
</div>
</div>
</div>
Those three ballots sum up the entire experiment better than a spreadsheet of numbers:
1. "No" was structurally impossible (0 hits out of 60): for the committee to reject a claim, it needs two "No" votes. Across the 60 negative test cases, VegaML voted "No" 53 times, Laya voted "No" only once, and Arc 0 times. Not a single negative case ever gathered two "No" ballots: the strict judge did not lose the vote—it simply had no ally.
2. The 66.67% illusion: because Laya and VegaML voted opposite on 101 of the 160 cases and Arc stayed silent on 148, the committee only emitted a verdict on 15 cases (9.38% coverage). It got 10 of those 15 right (66.67%, with a 95% Wilson interval of 41.7% to 84.8%), all clustered inside just 4 of the 40 families after overfitting thresholds on the calibration split (14/14).
3. Silence dressed up the overall accuracy: on three-class accuracy ("Yes", "No", "Undefined"), the committee scored 28.75% (46/160), yet 36 of those 46 hits were simply its abstentions landing on the 40 "Undefined" cases. A one-line script that always answers "Undefined" already scores 25.00% without spending RAM or waiting half a minute:
<div class="scoreboard" role="region" aria-label="Comparative scoreboard of the 2-of-3 judge committee against each standalone model and the Always Undefined baseline">
<h4 class="scoreboardtitle">Final scoreboard across the 160 test cases (60 "Yes" · 60 "No" · 40 "Undefined")</h4>
<p class="scoreboardsub">Contrast between accuracy when the evaluator dares to decide (selective accuracy + coverage) and overall three-class accuracy.</p>
<div class="score-row">
<div class="score-rowtop">
<span><strong>🏆 Arc Decide 0.4B (solo)</strong> — Best standalone model</span>
<span><code>0.59 GiB</code> · <code>4.21 s</code> cold · <code>49</code> FP · <code>5/60</code> on "No"</span>
</div>
<div class="score-bars">
<div class="score-metric">
<div class="score-metrichead"><span>Hit rate when deciding (coverage 60.63%)</span><strong>47.42%</strong></div>
<div class="bar-track"><div class="bar-fill bar-fill--amber" style="width:47.4%;"></div></div>
</div>
<div class="score-metric">
<div class="score-metric__head"><span>3-class accuracy (68/160)</span><strong>42.50%</strong></div>
<div class="bar-track"><div class="bar-fill bar-fill--green" style="width:42.5%;"></div></div>
</div>
</div>
</div>
<div class="score-row">
<div class="score-rowtop">
<span><strong>Laya 0.4.11 (solo)</strong> — The optimist</span>
<span><code>2.26 GiB</code> · <code>13.83 s</code> cold · <code>73</code> FP · <code>52/60</code> on "Yes"</span>
</div>
<div class="score-bars">
<div class="score-metric">
<div class="score-metrichead"><span>Hit rate when deciding (coverage 80.00%)</span><strong>41.41%</strong></div>
<div class="bar-track"><div class="bar-fill bar-fill--cyan" style="width:41.4%;"></div></div>
</div>
<div class="score-metric">
<div class="score-metric__head"><span>3-class accuracy (66/160)</span><strong>41.25%</strong></div>
<div class="bar-track"><div class="bar-fill bar-fill--cyan" style="width:41.25%;"></div></div>
</div>
</div>
</div>
<div class="score-row">
<div class="score-rowtop">
<span><strong>VegaML 0.11.0 (solo)</strong> — The pessimist</span>
<span><code>4.93 GiB</code> · <code>13.66 s</code> cold · <code>4</code> FP · <code>51/60</code> on "No"</span>
</div>
<div class="score-bars">
<div class="score-metric">
<div class="score-metrichead"><span>Hit rate when deciding (coverage 78.13%)</span><strong>40.80%</strong></div>
<div class="bar-track"><div class="bar-fill bar-fill--rose" style="width:40.8%;"></div></div>
</div>
<div class="score-metric">
<div class="score-metric__head"><span>3-class accuracy (61/160)</span><strong>38.13%</strong></div>
<div class="bar-track"><div class="bar-fill bar-fill--rose" style="width:38.13%;"></div></div>
</div>
</div>
</div>
<div class="score-row">
<div class="score-rowtop">
<span><strong>⚖️ 2-of-3 Committee (Laya + VegaML + Arc)</strong> — Deadlock by opposite biases</span>
<span><code>~31.7 s</code> serial · <code>3</code> FP · <strong><code>0/60</code> on "No"</strong></span>
</div>
<div class="score-bars">
<div class="score-metric">
<div class="score-metrichead"><span>Hit rate when deciding (10/15 · coverage 9.38%)</span><strong>66.67%</strong></div>
<div class="bar-track"><div class="bar-fill bar-fill--amber" style="width:66.7%;"></div></div>
</div>
<div class="score-metric">
<div class="score-metric__head"><span>3-class accuracy (36 of 46 are abstentions)</span><strong>28.75%</strong></div>
<div class="bar-track"><div class="bar-fill bar-fill--rose" style="width:28.75%;"></div></div>
</div>
</div>
</div>
<div class="score-row">
<div class="score-rowtop">
<span><strong>Trivial baseline: always answer "Undefined"</strong></span>
<span><code>0.00 GiB</code> · <code>0 ms</code> · <code>0</code> FP</span>
</div>
<div class="score-bars">
<div class="score-metric">
<div class="score-metrichead"><span>Hit rate when deciding (coverage 0.00%)</span><strong>N/A</strong></div>
<div class="bar-track"><div class="bar-fill" style="width:0%;"></div></div>
</div>
<div class="score-metric">
<div class="score-metric__head"><span>3-class accuracy (40/160 free hits)</span><strong>25.00%</strong></div>
<div class="bar-track"><div class="bar-fill bar-fill--cyan" style="width:25.0%;"></div></div>
</div>
</div>
</div>
</div>
---
Research takeaways: which open model could run in milliseconds on my i7-8550U
When would a JEV-style classifier committee actually make sense? When each judge clears 50% accuracy on every class out-of-sample (Condorcet 1785[^condorcet1785]), when their errors are uncorrelated (Dietterich 2000[^dietterich2000]), when their probabilities are properly calibrated (Guo et al. 2017[^guo2017]), and when at least two judges have real sensitivity to vote "No". Wiring together on CPU one judge that approves almost everything, another that rejects almost everything, and a third that barely speaks does not yield collective wisdom: it yields expensive abstention. That is why I retired the prototype.
Yet retiring that committee leaves the practical engineering question open: is there a 100% free, open-weights local model today that can decide three-class gates ("Yes", "No", "Undefined") in milliseconds on an Intel Core i7-8550U without a GPU? I believe so, provided I switch architectural families and stop treating logical verification as a text-generation problem; but that is a hypothesis this experiment did not test.
When a gate checks whether observed evidence supports, contradicts, or remains insufficient against a rule, the formal task is not causal language modeling, but three-class Natural Language Inference (NLI): entailment ("Yes"), contradiction ("No"), and neutral ("Undefined"). In that category, the candidate I propose to measure next is cross-encoder/nli-deberta-v3-small, built on the DeBERTaV3 architecture (He, Gao, and Chen 2023[^he2023]); its repository also ships an ONNX INT8 build for AVX2 CPUs that runs with onnxruntime, and optimum can export others. The idea of reusing an NLI model as a classifier comes from Laurer et al. (2024[^laurer2024]), whose model family includes a larger variant, MoritzLaurer/DeBERTa-v3-base-mnli-fever-anli. I have not yet measured either one on my 160-case bank:
<div class="nli-solution-card" role="region" aria-label="Technical specification of the open model I propose to measure on CPU: cross-encoder/nli-deberta-v3-small in ONNX INT8">
<div class="nli-solution-cardtop">
<h3 class="nli-solution-cardtitle">Hypothesis to measure on CPU: nli-deberta-v3-small (ONNX INT8)</h3>
<div class="jev-chips">
<a class="jev-chip" href="huggingface.co" target="_blank" rel="noopener">HF Model (Apache)</a>
<a class="jev-chip jev-chip--amber" href="arxiv.org" target="_blank" rel="noopener">DeBERTaV3 Paper</a>
<a class="jev-chip" href="onnxruntime.ai" target="_blank" rel="noopener">ONNX Runtime</a>
</div>
</div>
<p class="nli-solution-carddesc">
Bidirectional <em>cross-encoder</em> with <strong>disentangled attention</strong> (separating content and relative position) pre-trained via <em>replaced token detection</em> (ELECTRA) and fine-tuned on <code>SNLI</code> + <code>MultiNLI</code>. It evaluates premise and hypothesis jointly in a single forward pass without loading PyTorch.
</p>
<div class="nli-solution-cardgrid">
<div class="nli-solution-cardmetric">
<strong>Latency still to be measured</strong>
I did not run it on this bank. Because it decides in a single pass without generating text, my hypothesis is that it will land well below the committee's <code>366–1,717 ms</code> warm and <code>~31.7 s</code> cold.
</div>
<div class="nli-solution-cardmetric">
<strong>~165 MiB on disk (ONNX INT8 for AVX2)</strong>
<code>44M</code> backbone parameters (<code>142M</code> total with vocabulary embeddings); the <code>model_quint8_avx2.onnx</code> file takes about <code>165 MiB</code> on disk. Its runtime RAM is still to be measured, so I do not yet compare it with the roughly <code>7.8 GiB</code> of RAM used by the three judges.
</div>
<div class="nli-solution-card__metric">
<strong>3 native classes ("Yes" / "No" / "Undefined")</strong>
Emits direct logits for <code>contradiction</code>, <code>entailment</code>, and <code>neutral</code> (<code>87.55%</code> on MNLI <em>mismatched</em>, according to its model card). Whether that fixes the <code>"No"</code> blindness (<code>0/60</code>) on my gates remains to be measured.
</div>
</div>
</div>
The takeaway I keep from this proof of concept has a measured part and an unmeasured one. Measured: on a work laptop without a dedicated accelerator, a committee of mismatched models did not beat its best individual judge on three-class accuracy and never managed to say "No". Still a hypothesis: that a single small NLI cross-encoder, calibrated and compiled to ONNX INT8, would beat it in latency, memory footprint, and sensitivity to say "No". When verification is deterministic (a hash, a JSON schema, or an exit code), a 0 ms code rule remains unbeatable; and when I genuinely need to judge semantic entailment or contradiction locally, my next step is not to stack three judges in series, but to measure an architecture designed for that task first.
---
References
[^arc532025]: Arc53. 2025. "arc-decide-0.4b-v0.2: Compact ONNX Decision Classifier". Hugging Face model repository. huggingface.co.
[^browseruse2026]: Browser Use and TypeSafe AI. 2026. "JEV Ultrafast: Sub-Second Browser Agent Actions with Jev Decision Models". Official GitHub repository. browser-use/jev-ultrafast.
[^condorcet1785]: Condorcet, Jean-Antoine-Nicolas de Caritat, Marquis de. 1785. Essai sur l'application de l'analyse à la probabilité des décisions rendues à la pluralité des voix. Paris: Imprimerie Royale.
[^dietterich2000]: Dietterich, Thomas G. 2000. "Ensemble Methods in Machine Learning". In Multiple Classifier Systems (MCS 2000), Lecture Notes in Computer Science, vol. 1857, 1–15. Berlin: Springer. Scholar
[^guo2017]: Guo, Chuan, Geoff Pleiss, Yu Sun, and Kilian Q. Weinberger. 2017. "On Calibration of Modern Neural Networks". In Proceedings of the 34th International Conference on Machine Learning (ICML), PMLR 70: 1321–1330.
[^he2023]: He, Pengcheng, Jianfeng Gao, and Weizhu Chen. 2023. "DeBERTaV3: Improving DeBERTa using ELECTRA-Style Pre-Training with Gradient-Disentangled Embedding Sharing". In International Conference on Learning Representations (ICLR 2023). arXiv · Scholar
[^laurer2024]: Laurer, Moritz, Wouter van Atteveldt, Andreu Casas, and Kasper Welbers. 2024. "Less Annotating, More Classifying: Addressing the Data Scarcity Issue of Supervised Machine Learning with Deep Transfer Learning and BERT-NLI". Political Analysis 32 (1): 84–100. Model from the same family: huggingface.co. DOI · Scholar
[^nandhakishorm2026a]: NandhaKishorM (ConvAI Innovations). 2026a. "Laya: System 1 Non-Autoregressive Multilingual Decision Engine". GitHub repository. NandhaKishorM/laya.
[^nandhakishorm2026b]: NandhaKishorM. 2026b. "VegaML: Potential-Well Physics Decision Engine over Frozen Language Backbones". GitHub repository. NandhaKishorM/vegaml.
Mentions
@OmarchyUpdates Primarily kitty because I heard the developer (who also does calibre ebook manager) on a podcast and was really impressed. github.com/kovidgoyal
Multi-agent work in three spoonfuls (part IV): from a terminal trident to an autopoietic loop --- title: "Multi-agent work in three spoonfuls (part IV): from a terminal trident to an autopoietic loop" published: true description: "Fourth entry in the penta-agent multi-agent series: quota-governed routing, 70 ms hybrid memory, MCP tools, and a zero-token local autopoiesis loop in Harness2." tags: "ai, agents, cli, automation" canonical_url: "3cucharadas.cl" cover_image: "3cucharadas.cl" ai_disclosure_level: "some_ai" --- After benchmarking the models in part I, auditing retrieval in part II, and tracing provenance in part III of this series, I closed my laptop with a sense of victory: I had a trident of agents running from the terminal on Arch Linux. With a couple of zsh aliases, I could invoke Claude Code for architectural reasoning, hand off a task to Codex CLI to edit code, or ask Gemini CLI and Antigravity for a quick second opinion. On paper, orchestration looked solved. Yet after using that setup every day on real projects inside penta-agent, I hit a silent wall: having three agents talking does not equal having a system that learns. Every time I opened a fresh session, the trident suffered from partial amnesia, repeated commands that had already failed the previous week, burned the quota of the most expensive provider on routine tasks, or marked tests as "verified" when they had never had a chance to fail. To understand what was missing, it helped to change the question. In a recent systems-theory analysis of artificial intelligence, Benedikt Zönnchen, Mariya Dzhimova, and Gudrun Socher (2025[^zonnchen2025], 2–4) propose setting aside whether a language model "thinks like a human" and asking instead the question posed by Humberto Maturana and Francisco Varela (1987[^maturana1987] [1984]) and extended by Niklas Luhmann (1998[^luhmann1998], 60–69): can the system draw its own boundary with the environment, observe its own failures, and sustain itself through its own operations? In other words, moving from the vague notion of "intelligence" to the concrete mechanism of autopoiesis. As Zönnchen, Dzhimova, and Socher (2025[^zonnchen2025], 8–10) show, an isolated language model in a chat window neither is nor can be an autopoietic, sense-making system: it lacks what George Spencer-Brown (1969[^spencerbrown1969]) called re-entry—the capacity to re-introduce the distinction between system and environment (self-reference vs. other-reference) inside its own operations—because it only computes which token is statistically plausible after another, without internal resistance against error. If I want a system that improves without degrading, I have to build a socio-technical harness around the models that couples the probabilistic flexibility of neural networks with the strict coupling and binary code (works / does not work, work / fail) of deterministic technology described by Luhmann (1998[^luhmann1998], 517–525) and André Reichel (2011[^reichel2011], 105–118). The starting point: what I measured and discarded before making this leap Before diving into the three spoonfuls of this fourth installment, here is the experiment that forced me to adopt that discipline. When I tried to give the system long-term memory, the obvious temptation was to install the most elaborate architecture available: temporal graphs, heavy extractors, or an 8B-parameter neural judge running on CPU. Instead of following intuition, I built a reproducible benchmark over my real work logs—comparing open alternatives such as GraphRAG, Graphiti, Hindsight, Letta, Mem0, and deja-vu—and set a falsification contract upfront: any candidate exceeding 0.10 s in p95 latency or failing to improve recall by at least 10% would be discarded. | What I tested in the laboratory | Measured result | Operational decision | |---|---|---| | Hybrid memory (v3.1) (FTS5 lexical index + semantic neighbors in Qdrant with Qwen3-Embedding-0.6B) | Latency p95 = 0.07 s (< 0.10 s), 96% overall recall, rescuing 1 in 3 zero-lexical-overlap queries | Promoted to production as the engine behind experience-memory and recall-context | | In-memory relational graph (v3.2) for multi-hop entity expansion | Exact tie in accuracy with v3.1, but nearly double the latency (p95 = 0.13 s > 0.10 s) | Frozen in the lab; the extra complexity did not earn its keep | | CPU neural judges (4B and 8B) for live answer auditing | Between 69 s and 197 s per verdict, hitting 180 s timeouts in 2 of 3 runs | Discarded from the critical path; pruned 36.3 GiB from disk | | Deterministic checks + bounded 0.6B judge for local validation | Millisecond latency, 0 remote calls, and 100% reproducibility | Adopted as the standard for control gates and evaluation | Table 1. Summary of the prior local memory and evaluation laboratory in penta-agent: what survived the 0.10 s threshold and why I pruned 36.3 GiB of local models that added no operational value. With that foundation in place, I organized this fourth part into three progressive spoonfuls: in the first, I show how I moved from launching standalone agents by hand to governing them with quota budgets, auditable bridges, and a live board in kitty and tmux; in the second, how the nervous system of hybrid memory, MCP tools, and skills works under the hood; and in the third, how I closed the local autopoiesis loop with Harness2 and where both my metrics and systems theory draw the boundary today. --- Spoonful 1: From invoking agents by hand to governing agents and models In plain terms: when I first wired the three agents together, I acted like a traffic officer waving my arms in the middle of an intersection. If I wanted Codex CLI to review a patch written by Claude Code, I copied file paths, opened another tab, and hoped for the best. That works for a five-minute demo, but it falls apart when a task runs for two hours and touches twenty files. Quota-aware routing and security boundaries My first deductive inference came from a hard constraint: model subscriptions and APIs have usage limits, different context windows, and credential boundaries that must never blur. By definition, if I delegate a heavy task to an agent whose quota is at 98%, the session will die mid-flight and leave the repository in an inconsistent state. So I replaced intuitive provider selection with an explicit policy in routing.yaml and a pre-flight sentinel (quota_status.sh, governed by the quota-guard skill). Before launching any expensive job, the system reads cached pressure across every lane without spending tokens: - 🔍 Claude Code (Opus / Sonnet): handles architectural design, delicate editing, and long-horizon synthesis when its quota is clear (exit 0). - 🛠️ Codex CLI (gpt-5.4): steps in as an implementation peer, deep refactoring engine, session rescuer (codex-rescue), and cross-validator. - 🌐 Gemini CLI and Antigravity (gemini-3-pro / flash): in a direct session (penta-agy) it acts as the primary integrator; when invoked from outside via agy-bridge, it runs inside a strict sandbox over sanitized public context as an explorer, reviewer, or validator, never inheriting private keys or .env files. Instead of calling a raw binary and depending on whatever it prints to stdout, every cross-agent handoff goes through agy-bridge. The bridge requires declaring who is calling (--caller), in what mode (plan, review, patch, test, or explain), and with what time limit (--timeout), leaving an immutable receipt in .agents/runs/<run_id>/ with request.md, result.md, status.json, and diff.patch. The live board (plan-board) and decision gates My second inference was inductive: reviewing dozens of past sessions showed that the biggest waste of time happened at two extremes. Either an agent interrupted me every two minutes to ask permission for trivial, reversible steps, or it silently made a delicate architectural choice and I only discovered at the end that it had gone down the wrong path. To eliminate both extremes without filling this post with abstract flowcharts, here is how my actual kitty terminal—or minimalist Wayland alternatives like foot on Codeberg—looks today when split into two panes with tmux during a live task:  Watch the full video demo on 3cucharadas.cl. <strong>Figure 1.</strong> Daily workflow in my <a href="kovidgoyal/kitty"><code>kitty</code></a> + <a href="tmux/tmux"><code>tmux</code></a> terminal with the <a href="starship/starship"><code>Starship</code></a> prompt: the top pane runs multi-agent delegation via <code>agy-bridge</code>, the <code>decision-gate</code> brake, and <code>pytest</code>; the bottom pane (<code>watch.mjs</code>) updates each step live (<code>[ ]</code> → <code>[~]</code> → <code>[!]</code> → <code>[x]</code>), along with binding decisions and drift. What appears in the bottom pane of Figure 1 is the contract that changed how I work: 1. Local autonomy with visual traceability (plan-board): every reversible, in-scope step proceeds without asking permission, but must be reflected in real time in the bottom table. And no item can be closed as verified ([x]) unless the agent attaches the concrete test, command, or observation reference that backs it. 2. Decision gate (decision-gate): when an irreversible or architectural fork appears (state [!]), the agent halts only that branch and presents the question with the recommended option first, marked (Recommended) and justified with deductive, inductive, and abductive evidence. 3. A gate that has never been seen red is not a gate (gates-falsables): before accepting any new verifier, I require running it against a synthetic failure (--fixture) and proving that it returns a non-zero exit code (exit 1). If a check passes even when I break its input on purpose, it is not a safety net—it is compliance theater. --- Spoonful 2: The nervous system — hybrid memory, skills, and MCP tools If the first spoonful orders who does what and under which rules, the second solves how the system remembers what it has already learned and how it picks the exact tool without bloating the context window. Here the diagnosis by Zönnchen, Dzhimova, and Socher (2025[^zonnchen2025], 6–7, 9) is decisive again: a neural network maintains a loose coupling with human communication that behaves like a "contingent index-card system (Zettelkasten)" (pp. 7, 9) of semantic associations in vector space, giving rise to what Elena Esposito (2017[^esposito2017], 249–265; 2022[^esposito2022]) calls "virtual double contingency" and "artificial communication." That flexibility lets it connect ideas phrased in very different words, but also makes its outputs inherently probabilistic and devoid of autonomous decision-making. If I want reliable memory and precise execution, I have to couple that vector Zettelkasten with exact indices and deterministic scripts. Experience memory (experience-memory): the hybrid Zettelkasten in 0.07 s When I first started keeping logs, my memory was essentially a folder of Markdown files that I read or searched with ripgrep. The obvious problem is that if a month ago I solved a cold-boot screen freeze under the title "Webview failure on autostart" and today I search for "Panel fails to load at login", a purely lexical search can miss it entirely, whereas a purely vector search can bury the exact name of a script like verify_boot_contract.sh. The solution I validated in Table 1 combines both worlds behind the experience-memory MCP server and the recall-context skill: - Exact lexical lane (SQLite FTS5): instantly catches flag names, error codes, file paths, and invariants (INV-005). - Dense semantic lane (Qdrant + Qwen3-Embedding-0.6B): indexes architectural decisions, handoffs, and operational lessons (penta_context_v2) to retrieve conceptual neighbors even when they share zero keywords. Before designing any non-trivial strategy, the agent queries recall_experience in 70 milliseconds (p95 = 0.07 s). That is how it discovers which command worked previously, which hypothesis was already refuted, and which environment trap to avoid (for instance, knowing that in my shell cp, mv, and rm are aliased to interactive -i, which hangs a headless process unless invoked via command mv -f). Skills as living procedures and proactive MCP selection To avoid saturating the initial prompt with thousands of lines of instructions, I adopted the modular pattern of Anthropic Skills enriched with local contracts. In penta-agent, each skill is a self-contained package with four parts: a concise contract in SKILL.md defining when to activate and when not to use it; on-demand deep documentation in references/ (such as the editorial corpus extracted with Docling or diagramming rules with D2); deterministic executables in scripts/ (such as typed pipelines in Nushell, visual automation with Playwright, or forge integration via glab on GitLab); and a telemetry trail. Similarly, the fleet of MCP servers (plan-board, experience-memory, ideas-rag, paper-search, bibliography-apa, PLAYWRIGHT_LOCAL) is cataloged in specs/mcp-capabilities.json. When a task arrives, triage evaluates which capabilities provide real evidence and records both hits and justified abstentions. And when I found that two older servers (quota status and remote SSH infrastructure) were faster, clearer, and easier to audit as direct scripts (quota_status.sh and remote_exec.sh), I decommissioned them as MCP servers and turned them into lightweight skills. Fewer resident daemons mean a smaller failure surface. --- Spoonful 3: The autopoiesis loop (Harness2) — how the system rehearses its own improvements Here I reach the core of this fourth installment. Having capable agents (Spoonful 1) and fast hybrid memory with skills (Spoonful 2) still leaves a critical question open: what happens when a delegation route ages, a skill starts inducing errors, or a memory tweak degrades accuracy on edge cases? If I rely solely on noticing by eye weeks later, the system degrades through silent drift. Why a standalone LLM lacks re-entry and internal resistance In their study on autopoiesis and artificial intelligence, Zönnchen, Dzhimova, and Socher (2025[^zonnchen2025], 8–9) explain with surgical precision why asking a model to "reflect on its own errors" via chain-of-thought (CoT) is not enough. When a model generates intermediate tokens like "Is this step correct?", it exhibits only rudimentary processual self-referentiality (p. 8)—producing the most statistically plausible continuation inside its training distribution—while lacking reflective self-reference and genuine re-entry (Spencer-Brown 1969[^spencerbrown1969]). If a model takes itself as its sole reference without external contrast, it quickly falls into infinite recursion or collapse; if it depends entirely on a human retraining its weights from outside (RLHF or delayed fine-tuning), it remains an allopoietic artifact determined from the outside (Zönnchen, Dzhimova, and Socher 2025[^zonnchen2025], 4, 8–9). To escape that trap, Zönnchen, Dzhimova, and Socher (2025[^zonnchen2025], 7) recover a decisive formulation from Niklas Luhmann (1995[^luhmann1995]) on how operational constructivism relocates Kant's "resistance of reality" inside a system: > "I think we should not abandon [Kant's] idea of resistance, but we should relocate it into the system. It is the result of resolving an internal conflict—the result of the system's operations resisting the operations of the same system" (Luhmann 1995[^luhmann1995], quoted in Zönnchen, Dzhimova, and Socher 2025[^zonnchen2025], 7). That sentence describes, piece by piece, what I built in penta-agent by adapting and integrating the proactive loop of Harness² proposed by Ruiyao Xu, Yanfei Chen, Zhongying CuiZhu, et al. (2026[^xu2026]): making the system's own deterministic verification operations resist and filter change proposals generated from its own operational friction. <details markdown="1"> <summary><strong>In plain terms (ELI5): what is Google's original Harness² and how did I adapt it to my machine?</strong></summary> Imagine your AI agents are very creative chefs, but the recipe book they follow (their rules, memory, and tools) sometimes has confusing steps that make them burn the rice. The original Harness² from Google Research (Xu et al. 2026) proposes a clever loop called Propose–Probe–Compose: instead of swapping out the chef's brain, it puts several assistants to work rewriting the recipe book, asks them to cook test dishes in the cloud, and keeps the winning recipe. For my daily workflow, the factory setup had two catches: it is designed to burn hundreds of paid cloud model calls (Vertex AI), and when driving CLI agents it unbuckles their seatbelt (--dangerously-bypass-approvals-and-sandbox) with open internet access. To adapt it to penta-agent without spending an extra cent or opening security holes, I took its recursive search engine (commit 1cfe254e) and locked it inside a "test kitchen" completely unplugged from the internet (unshare -Urn), with a disposable home folder and zero access to my API keys or model CLIs (model_calls = 0). Instead of running cloud benchmarks, my wrapper (penta-harness2 and local-cycle) feeds that test kitchen with the real stumbles my agents suffered during the week (CSI), requires any recipe tweak to first fail the test when broken (red) and then pass every historical case without breaking anything else (green), and finally stages the winning recipe across all three agents (Claude, Codex, and Gemini/Antigravity) with a one-step undo button (rollback-local) in case I do not approve it. </details> <figure class="d2-responsive" style="width: 100%;"> <img src="3cucharadas.cl" width="1001" height="954" style="width: 100%; height: auto; display: block; border-radius: 12px;" alt="Diagram of the closed local autopoiesis loop in Penta Agent with Harness2: CSI friction signals feed the case generator and the local cycle across routing, memory, and skills; a deterministic judge evaluates against holdout cases with zero model calls, discarding regressions and keeping only verified improvements for human promotion."> <figcaption><strong>Figure 2.</strong> Governed autopoiesis loop in <code>penta-agent</code> + <code>Harness2</code>: relocating internal resistance (Luhmann 1995; Zönnchen, Dzhimova, and Socher 2025) through <code>holdout</code> evaluation with <code>model_calls = 0</code> prior to any human promotion.</figcaption> </figure> How the closed loop operates across my three domains (routing, memory, skills) As Figure 2 shows (adapting into a three-column horizontal layout on desktop and a vertical flow on mobile), the loop operates in four strict stages: 1. Observing real friction (CSI — Continuous Self-Improvement): while I use the system, a collector logs objective friction signals: a task that had to switch agents after a timeout, an experience-memory query that returned too few useful neighbors, or a skill where the user had to correct a command. 2. Bridging evidence into reproducible cases (--from-csi latest): the local_cycle.py module takes that friction report and automatically translates it into a test specification (CaseSpec) inside an isolated environment, without touching my active configuration. 3. Internal resistance without spending tokens (eval_harness with model_calls = 0): the harness runs the full suite (--profile autopoiesis-all, currently covering 9/9 baseline cases across routing, memory, and skills), enforcing two hard conditions: every control case (holdout) must pass (holdout_passed = true), and external API calls must equal zero (model_calls = 0). 4. Auditable decision (KEEP vs. DISCARD) and human promotion: if a candidate degrades even a single holdout case or fails to beat the baseline, the deterministic judge discards it (DISCARD). Only when it improves the score with zero regressions does it receive a KEEP verdict and leave a signed receipt for me to review before promoting it to the main repository. So this does not remain a theoretical promise, the next mini-video shows penta-harness2-shadow local-cycle --profile autopoiesis-all running in my kitty + tmux terminal, including what happens when I inject a regressive candidate (--fixture) alongside a healthy improvement:  Watch the full video demo on 3cucharadas.cl. <strong>Figure 3.</strong> Execution in my <a href="kovidgoyal/kitty"><code>kitty</code></a> + <a href="tmux/tmux"><code>tmux</code></a> terminal of the local autopoiesis loop (<code>local-cycle --profile autopoiesis-all</code>): it evaluates all <code>9/9</code> cases in <code>routing</code>, <code>memory</code>, and <code>skills</code> with <code>model_calls = 0</code>, applies internal resistance to reject the regressor (<code>DISCARD</code>), and preserves the verified improvement (<code>KEEP +0.250</code>) with all <code>82</code> harness tests green. --- Closing: what my architecture achieves today and where its limits lie Looking back at the path from part I, part II, and part III, the main difference is no longer which model writes the prettiest reply to an isolated prompt, but the structure that holds the whole system together when I am not watching every line. Following the rigorous distinction drawn by Zönnchen, Dzhimova, and Socher (2025[^zonnchen2025], 5, 9–10) and by Elena Esposito (2017[^esposito2017]; 2022[^esposito2022]; 2024[^esposito2024]), it would be an epistemic mistake to claim that a language model or a bundle of scripts has on its own achieved the biological autopoiesis of a living cell (Maturana and Varela 1987[^maturana1987] [1984]) or the reflective sense-making (Sinn) of human consciousness (Luhmann 1998[^luhmann1998], 50–69). As Zönnchen, Dzhimova, and Socher (2025[^zonnchen2025], 5, 10) caution when critiquing merely metaphorical invocations of technological autopoiesis, language models remain statistical engines that compute distributions without mental states of their own. Yet—and this is my engineering synthesis for the socio-technical system as a whole—when I couple their capacity for contingent variation with verified hybrid memory, strict delegation contracts, a binary internal-resistance harness (work / fail; Reichel 2011[^reichel2011]) that filters its own proposals before touching production, and deliberative human oversight, I obtain in practice a loop of governed operational autopoiesis. To close with full transparency, Table 2 summarizes what is running and measured on my machine today, where the next step points, and under what objective condition I would discard each component if it stopped earning its keep: | System pillar | What it achieves today (verified in production) | What it aims to achieve next & falsification condition | |---|---|---| | 1. Agent and model routing (routing.yaml, quota-guard, agy-bridge) | Routes tasks across Claude Code, Codex CLI, and Gemini CLI / Antigravity based on cached quota pressure; isolates handoffs in .agents/runs/ under a strict sandbox and displays live progress in plan-board (Figure 1). | Goal: reweight routing priorities from historical domain success rates.<br>Discard if: the bridge introduces spurious failures or bureaucratic latency exceeding quota savings. | | 2. Hybrid memory (experience-memory, Qdrant + FTS5) | Resolves lexical and semantic queries in p95 = 0.07 s (< 0.10 s), rescues 33% of zero-keyword-overlap pairs, and saves 36.3 GiB after pruning slow CPU judges (Table 1). | Goal: add automatic decay for obsolete lessons when a contract changes.<br>Discard if: p95 latency exceeds 0.10 s or semantic noise degrades top-3 precision. | | 3. Skills and MCP governance (mcp-fleet, gates-falsables) | Maintains declarative parity across agents (24/24 checks green), measures MCP usage and abstention, and requires every new gate to fail first against a red canary (--fixture -> exit 1). | Goal: semi-automatic pruning of skills that accumulate repeated friction in CSI telemetry.<br>Discard if: maintaining a skill's contract takes longer than running the direct command. | | 4. Local autopoiesis (Harness2) (local-cycle, eval_harness) | Converts real CSI friction into reproducible Cases and evaluates candidates across routing, memory, and skills (9/9 cases, 82/82 tests) with model_calls = 0, applying internal resistance (KEEP / DISCARD, Figures 2 and 3). | Goal: expand the bank of real cases extracted from failed sessions without losing millisecond evaluation.<br>Hard boundary (INV-004): blind auto-merge is forbidden; final promotion to production always requires human review. | Table 2. Balance between verified production results in penta-agent today, the design horizon, and the falsification thresholds that keep the system under human control. If building this fourth stage made one thing clear to me, it is that the maturity of a multi-agent system is not measured by how many new pieces I bolt onto it each week, but by how much unnecessary complexity I can prune and how many of its own mistakes the system can catch before asking for my help. --- References [^esposito2017]: Esposito, Elena. 2017. "Artificial Communication? The Production of Contingency by Algorithms." Zeitschrift für Soziologie 46 (4): 249–265. Scholar [^esposito2022]: Esposito, Elena. 2022. Artificial Communication: How Algorithms Produce Social Intelligence. Cambridge, MA: The MIT Press. Scholar [^esposito2024]: Esposito, Elena. 2024. Kommunikation mit unverständlichen Maschinen. Salzburg and Vienna: Residenz Verlag. Review of Kommunikation mit unverständlichen Maschinen by Eric Van der Beek in merz | medien + erziehung: DOI · Scholar [^luhmann1995]: Luhmann, Niklas. 1995. "Systems Theory and Postmodernism." University lecture, London. Quoted in Zönnchen, Dzhimova, and Socher, From Intelligence to Autopoiesis (2025, 7): DOI · Scholar [^luhmann1998]: Luhmann, Niklas. 1998. Die Gesellschaft der Gesellschaft. Frankfurt am Main: Suhrkamp Verlag. <search.worldcat.org>. [^maturana1987]: Maturana, Humberto R., and Francisco J. Varela. 1987 [1984]. El árbol del conocimiento: las bases biológicas del entendimiento humano. Santiago de Chile: Editorial Universitaria. 1st Chilean ed. 1984; 1987 international ed. cited in Zönnchen, Dzhimova, and Socher, From Intelligence to Autopoiesis (2025, 3): DOI · Scholar [^reichel2011]: Reichel, André. 2011. "Technology as System: Towards an Autopoietic Theory of Technology." International Journal of Innovation and Sustainable Development 5 (2–3): 105–118. Scholar [^spencerbrown1969]: Spencer-Brown, George. 1969. Laws of Form. London: Allen & Unwin. <archive.org>. [^xu2026]: Xu, Ruiyao, Yanfei Chen, Zhongying CuiZhu, Bhavana Dalvi Mishra, Yifei Ming, Han Yu, Rujun Han, Chen-Yu Lee, and Tomas Pfister. 2026. "Harness²: Recursive Agent Harnessing for an Open World." arXiv preprint arXiv:2610.14224 (open source at <google-research/harness2>). arXiv · Scholar [^zonnchen2025]: Zönnchen, Benedikt, Mariya Dzhimova, and Gudrun Socher. 2025. "From Intelligence to Autopoiesis: Rethinking Artificial Intelligence through Systems Theory." Frontiers in Communication 10:1585321. DOI · Scholar
JEV-style local judges in three spoonfuls: when voting improves a decision and when it only stalls it --- title: "JEV-style local judges in three spoonfuls: when voting improves a decision and when it only stalls it" published: true description: "Proof of concept of a 2-of-3 committee on CPU (Laya, VegaML, and Arc Decide) on an Intel Core i7-8550U, with an ONNX INT8 NLI cross-encoder (DeBERTa-v3-small) as an alternative still to be measured." tags: "aievaluation, localinference, cpu, decisionmaking" canonical_url: "3cucharadas.cl" cover_image: "3cucharadas.cl" ai_disclosure_level: "some_ai" --- When I automate code workflows and technical auditing, many verification checks do not need generated prose: they need a fast verdict between "Yes" (the evidence suffices), "No" (there is a hard failure), or "Undefined" (it is safer to abstain and escalate). Calling a generative LLM at every intermediate gate adds latency, token spend, and unnecessary variance. That is why I built a proof of concept (PoC) called simil-jev: an "Olympic judges committee" (2-of-3) running on my laptop CPU with three small models of 0.4B to 0.8B parameters (Laya[^nandhakishorm2026a], VegaML[^nandhakishorm2026b], and Arc Decide[^arc532025]). Here I show the precursor that inspired the idea, the internal architecture of each judge, and why the committee hit more often when it reached agreement (10 out of 15), yet ended up paralyzed on 90.62% of the test bank. --- Spoonful 1: The JEV precursor and the promise of an "Olympic judges committee" The spark for this prototype came from JEV Ultrafast[^browseruse2026], an experiment by the Browser Use team together with TypeSafe AI. Instead of asking a heavy LLM to inspect screenshots or write paragraphs at every browser step, jev-ultrafast turns the page into an indexed table of controls and delegates the choice to Jev, a specialized System 1 decision model that selects the atomic action (CLICK, SELECT, WAIT, BLOCKED) in milliseconds and only calls a small LLM when it needs to type text (TYPE_TEXT). <div class="jev-showcase"> <div class="jev-showcasetop"> <div class="jev-showcasebrand"> <span>⚡ JEV Ultrafast (Browser Use × TypeSafe AI)</span> </div> <div class="jev-chips"> <a class="jev-chip" href="browser-use/jev-ultrafast" target="_blank" rel="noopener"><i class="fab fa-github"></i> browser-use/jev-ultrafast</a> <a class="jev-chip jev-chip--amber" href="docs.typesafe.ai" target="_blank" rel="noopener">TypeSafe Jev Docs</a> </div> </div> <img src="raw.githubusercontent.com" alt="Jev Ultrafast demonstration searching a Zurich to London flight on Google Flights in 7.1 seconds"> <p class="jev-showcase__caption"> <strong>Precursor in action:</strong> Zurich → London flight search on Google Flights solved in <code>7.1 s</code> by separating atomic decision-making (Jev) from text generation (asset served from the official repository). </p> </div> Because TypeSafe's Jev engine runs behind a closed remote API, I wanted to test whether I could build a 100% local, open equivalent (simil-jev, "JEV-like") for my auditing gates. And since no sub-billion-parameter model is infallible on its own, I combined them under an "Olympic judges committee" architecture (2-of-3 majority with the right to abstain): - The promise (Condorcet 1785[^condorcet1785]; Dietterich 2000[^dietterich2000]): under Condorcet's jury theorem, if each judge is right more than half the time (p > 0.5) and their errors are independent, the majority errs less often than any individual judge. - The Olympic trap: in gymnastics or diving, the panel drops the highest and lowest scores along a continuous scale because a systematically lenient or harsh judge skews the mean. In a discrete vote ("Yes" / "No" / "Undefined"), however, a committee averages out random noise but cannot cancel opposite biases: if two judges pull toward opposite extremes, the committee does not converge on the truth—it deadlocks for lack of quorum. --- Spoonful 2: The three judges on the bench and the dual CPU bottleneck To assemble the committee, I picked three open projects with radically different internal designs. Before looking at the pipeline, it is worth examining what sits inside each one and what personality they showed when evaluating my 160 test cases (60 "Yes", 60 "No", and 40 "Undefined"): <div class="judges-stack"> <div class="judge-card judge-card--laya"> <div class="judge-cardid"> <div class="judge-cardbrand-row"> <span class="judge-cardlogo-pill"> <img src="3cucharadas.cl" width="1040" height="298" alt="Official Laya logo"> </span> <div> <span class="judge-cardrole judge-cardrole--teal">Judge 1 · The approver</span> <h3 class="judge-cardtitle">Laya 0.4.11</h3> </div> </div> <div class="jev-chips"> <a class="jev-chip" href="NandhaKishorM/laya" target="_blank" rel="noopener"><i class="fab fa-github"></i> GitHub</a> <a class="jev-chip" href="huggingface.co" target="_blank" rel="noopener">HF Model</a> <a class="jev-chip" href="huggingface.co" target="_blank" rel="noopener">Demo Space</a> </div> </div> <div class="judge-cardmain"> <p class="judge-carddesc"> Multilingual non-autoregressive <em>System 1</em> decision engine trained with <em>strictly proper scoring rules</em> (RLCD) to emit single-pass verdicts without generating text. </p> <div class="judge-card__stats"> <div><strong>CPU cost:</strong> <code>2.26 GiB</code> RAM · <code>13.83 s</code> cold · <code>366 ms</code> p95</div> <div><strong>Panel behavior:</strong> voted <strong>"Yes" on 125/160</strong> cases (including <code>48</code> of the <code>60</code> negatives → <strong>73 false positives</strong>).</div> </div> </div> </div> <div class="judge-card judge-card--vega"> <div class="judge-cardid"> <div class="judge-cardbrand-row"> <span class="judge-cardlogo-pill"> <img src="3cucharadas.cl" width="64" height="64" alt="Official VegaML potential-well icon"> </span> <div> <span class="judge-cardrole judge-cardrole--rose">Judge 2 · The rejecter</span> <h3 class="judge-cardtitle">VegaML 0.11.0</h3> </div> </div> <div class="jev-chips"> <a class="jev-chip jev-chip--rose" href="NandhaKishorM/vegaml" target="_blank" rel="noopener"><i class="fab fa-github"></i> GitHub</a> <a class="jev-chip jev-chip--rose" href="pypi.org" target="_blank" rel="noopener">PyPI 0.11.0</a> <a class="jev-chip jev-chip--rose" href="huggingface.co" target="_blank" rel="noopener"><code>Qwen3.5-0.8B</code></a> </div> </div> <div class="judge-cardmain"> <p class="judge-carddesc"> Couples a frozen reader (<code>Qwen3.5-0.8B</code>) with a compact <code>14.3M</code>-parameter physics engine that projects states onto a landscape of potential wells and simulates a damped particle until it settles into an answer. </p> <div class="judge-card__stats"> <div><strong>CPU cost:</strong> <code>4.93 GiB</code> RAM · <code>13.66 s</code> cold · <code>1,717 ms</code> p95</div> <div><strong>Panel behavior:</strong> voted <strong>"No" on 131/160</strong> cases and hit <strong>0 out of 60</strong> on the "Yes" class.</div> </div> </div> </div> <div class="judge-card judge-card--arc"> <div class="judge-cardid"> <div class="judge-cardbrand-row"> <span class="judge-cardicon-box" aria-hidden="true"> <svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M12 3v18"/><path d="M5 7h14"/><path d="M5 7l-3 6h6l-3-6z"/><path d="M19 7l-3 6h6l-3-6z"/><path d="M8 21h8"/></svg> </span> <div> <span class="judge-cardrole judge-cardrole--amber">Judge 3 · The silent one</span> <h3 class="judge-cardtitle">Arc Decide 0.4B</h3> </div> </div> <div class="jev-chips"> <a class="jev-chip jev-chip--amber" href="huggingface.co" target="_blank" rel="noopener">Arc53/arc-decide-0.4b</a> <a class="jev-chip jev-chip--amber" href="onnxruntime.ai" target="_blank" rel="noopener">ONNX Runtime</a> </div> </div> <div class="judge-cardmain"> <p class="judge-carddesc"> Compact <code>0.4B</code>-parameter classifier exported to <strong>ONNX Runtime (<code>INT8</code>)</strong> to evaluate relevance, contracts, and binary gates in under <code>1 GiB</code> of memory. </p> <div class="judge-card__stats"> <div><strong>CPU cost:</strong> <code>0.59 GiB</code> RAM · <code>4.21 s</code> cold · <code>950 ms</code> p95</div> <div><strong>Panel behavior:</strong> under its panel threshold (<code>0.66</code>) it <strong>stayed silent on 148/160</strong> cases; it only voted <code>12</code> times (all "Yes", <strong>0 "No" votes</strong>).</div> </div> </div> </div> </div> When I wired all three behind simil-jev --panel, the two bottlenecks depicted in Figure 1 surfaced immediately: <figure class="cuch-d2-fig"> <img src="3cucharadas.cl" width="1087" height="723" alt="Pipeline diagram of simil-jev --panel: input validation and hashes, three judges called sequentially on CPU, and a 2-of-3 quorum where Laya votes Yes, VegaML votes No, and Arc almost never votes, so the panel decides on only 9.38% of cases."> <figcaption> <strong>Figure 1.</strong> Real pipeline of <code>simil-jev --panel</code>. Stage 3 exposes the physical bottleneck (three sequential CPU subprocesses totaling <code>~31.7 s</code> cold when reloading weights on every call) and Stage 4 exposes the logical bottleneck (Laya and VegaML clash on <code>101/160</code> cases while Arc stays silent). </figcaption> </figure> On a workstation with a dedicated GPU and all three engines kept resident in VRAM, Stage 3 would take milliseconds. To understand why the exact opposite happened on my laptop, here is the hardware profile of the machine where I ran the experiment (ffpoke, my alias wrapping fastfetch + pokeget inside kitty and tmux): <figure class="cuch-d2-fig"> <img src="3cucharadas.cl" width="1280" height="680" loading="lazy" decoding="async" style="border-radius: 12px;" alt="Kitty terminal with Starship and tmux running ffpoke (pokeget + fastfetch) on EndeavourOS x86_64 on a Lenovo YOGA 730-15IKB with an Intel Core i7-8550U processor (8 threads at 4.00 GHz, 15 W TDP, AVX2), Intel UHD 620 integrated graphics, and 23.19 GiB of RAM without dedicated VRAM."> <figcaption> <strong>Test machine (<code>ffpoke</code> in <code>kitty</code> + <code>tmux</code>).</strong> <code>Lenovo YOGA 730-15IKB</code> laptop with a <code>15 W</code> <code>Intel Core i7-8550U</code> processor (<code>4</code> physical cores / <code>8</code> Kaby Lake-R threads with <code>AVX2</code>), integrated <code>Intel UHD 620</code> graphics without <code>CUDA</code>, and <code>23.19 GiB</code> of DDR4 RAM on <code>EndeavourOS</code>. </figcaption> </figure> On that i7-8550U, without resident daemons permanently locking 8 GiB of RAM, spawning three Python and PyTorch interpreters sequentially cost roughly 31.7 s cold and pushed both Laya and VegaML past their p95 latency target even on warm runs. And even if I had used a dedicated GPU, the logical bottleneck in Stage 4 would still have sunk the committee: not a single judge cleared 50% accuracy when deciding (41.41%, 40.80%, and 47.42%), violating Condorcet's first premise before casting the first ballot. --- Spoonful 3: The jury ballots and the 66.67% paradox To see why the committee hit 10 out of 15 when it reached agreement (66.67% selective accuracy) and still proved useless in practice, it suffices to inspect three real ballots from my 240-case bank (80 calibration and 160 test cases): <div class="duels-stack"> <div class="duel-card duel-card--paralisis"> <div class="duel-cardfamily">Family 1 · Contractual precedence (Why "No" vanished)</div> <div class="duel-cardquote">"An unsigned draft does not replace the signed record. The signed record says <code>red</code> and the draft says <code>green</code>. Is the active value <code>green</code>?" → <strong>Ground truth: "No"</strong></div> <div class="duel-card__ballots"> <span class="ballot ballot--yes">Laya: YES ✗</span> <span class="ballot ballot--no">VegaML: NO ✓</span> <span class="ballot ballot--mute">Arc: ABSTAIN (conf < 0.66)</span> <span class="ballot ballot--verdict-amber">2-of-3 Verdict: UNDEFINED (Deadlock)</span> </div> </div> <div class="duel-card"> <div class="duel-cardfamily">Family 2 · Direct evidence (When the tie-breaker certifies an error)</div> <div class="duel-cardquote">"The expected hash is <code>aa00</code> and the observed hash is <code>bb11</code>. Do the hashes match?" (<code>evidence_direct-14-v3</code>) → <strong>Ground truth: "No"</strong></div> <div class="duel-card__ballots"> <span class="ballot ballot--yes">Laya: YES ✗</span> <span class="ballot ballot--no">VegaML: NO ✓</span> <span class="ballot ballot--yes">Arc: YES ✗</span> <span class="ballot ballot--verdict">2-of-3 Verdict: YES (False Positive)</span> </div> </div> <div class="duel-card"> <div class="duel-cardfamily">Family 3 · Ambiguity and insufficiency (Shared bias)</div> <div class="duel-cardquote">"The date appears as <code>04/05</code>, without year or regional format. Is it May 4, 2026?" (<code>negation_ambiguity_insufficient-18-v2</code>) → <strong>Ground truth: "Undefined"</strong></div> <div class="duel-card__ballots"> <span class="ballot ballot--yes">Laya: YES ✗</span> <span class="ballot ballot--yes">VegaML: YES ✗</span> <span class="ballot ballot--mute">Arc: ABSTAIN</span> <span class="ballot ballot--verdict">2-of-3 Verdict: YES (False Positive)</span> </div> </div> </div> Those three ballots sum up the entire experiment better than a spreadsheet of numbers: 1. "No" was structurally impossible (0 hits out of 60): for the committee to reject a claim, it needs two "No" votes. Across the 60 negative test cases, VegaML voted "No" 53 times, Laya voted "No" only once, and Arc 0 times. Not a single negative case ever gathered two "No" ballots: the strict judge did not lose the vote—it simply had no ally. 2. The 66.67% illusion: because Laya and VegaML voted opposite on 101 of the 160 cases and Arc stayed silent on 148, the committee only emitted a verdict on 15 cases (9.38% coverage). It got 10 of those 15 right (66.67%, with a 95% Wilson interval of 41.7% to 84.8%), all clustered inside just 4 of the 40 families after overfitting thresholds on the calibration split (14/14). 3. Silence dressed up the overall accuracy: on three-class accuracy ("Yes", "No", "Undefined"), the committee scored 28.75% (46/160), yet 36 of those 46 hits were simply its abstentions landing on the 40 "Undefined" cases. A one-line script that always answers "Undefined" already scores 25.00% without spending RAM or waiting half a minute: <div class="scoreboard" role="region" aria-label="Comparative scoreboard of the 2-of-3 judge committee against each standalone model and the Always Undefined baseline"> <h4 class="scoreboardtitle">Final scoreboard across the 160 test cases (60 "Yes" · 60 "No" · 40 "Undefined")</h4> <p class="scoreboardsub">Contrast between accuracy when the evaluator dares to decide (selective accuracy + coverage) and overall three-class accuracy.</p> <div class="score-row"> <div class="score-rowtop"> <span><strong>🏆 Arc Decide 0.4B (solo)</strong> — Best standalone model</span> <span><code>0.59 GiB</code> · <code>4.21 s</code> cold · <code>49</code> FP · <code>5/60</code> on "No"</span> </div> <div class="score-bars"> <div class="score-metric"> <div class="score-metrichead"><span>Hit rate when deciding (coverage 60.63%)</span><strong>47.42%</strong></div> <div class="bar-track"><div class="bar-fill bar-fill--amber" style="width:47.4%;"></div></div> </div> <div class="score-metric"> <div class="score-metric__head"><span>3-class accuracy (68/160)</span><strong>42.50%</strong></div> <div class="bar-track"><div class="bar-fill bar-fill--green" style="width:42.5%;"></div></div> </div> </div> </div> <div class="score-row"> <div class="score-rowtop"> <span><strong>Laya 0.4.11 (solo)</strong> — The optimist</span> <span><code>2.26 GiB</code> · <code>13.83 s</code> cold · <code>73</code> FP · <code>52/60</code> on "Yes"</span> </div> <div class="score-bars"> <div class="score-metric"> <div class="score-metrichead"><span>Hit rate when deciding (coverage 80.00%)</span><strong>41.41%</strong></div> <div class="bar-track"><div class="bar-fill bar-fill--cyan" style="width:41.4%;"></div></div> </div> <div class="score-metric"> <div class="score-metric__head"><span>3-class accuracy (66/160)</span><strong>41.25%</strong></div> <div class="bar-track"><div class="bar-fill bar-fill--cyan" style="width:41.25%;"></div></div> </div> </div> </div> <div class="score-row"> <div class="score-rowtop"> <span><strong>VegaML 0.11.0 (solo)</strong> — The pessimist</span> <span><code>4.93 GiB</code> · <code>13.66 s</code> cold · <code>4</code> FP · <code>51/60</code> on "No"</span> </div> <div class="score-bars"> <div class="score-metric"> <div class="score-metrichead"><span>Hit rate when deciding (coverage 78.13%)</span><strong>40.80%</strong></div> <div class="bar-track"><div class="bar-fill bar-fill--rose" style="width:40.8%;"></div></div> </div> <div class="score-metric"> <div class="score-metric__head"><span>3-class accuracy (61/160)</span><strong>38.13%</strong></div> <div class="bar-track"><div class="bar-fill bar-fill--rose" style="width:38.13%;"></div></div> </div> </div> </div> <div class="score-row"> <div class="score-rowtop"> <span><strong>⚖️ 2-of-3 Committee (Laya + VegaML + Arc)</strong> — Deadlock by opposite biases</span> <span><code>~31.7 s</code> serial · <code>3</code> FP · <strong><code>0/60</code> on "No"</strong></span> </div> <div class="score-bars"> <div class="score-metric"> <div class="score-metrichead"><span>Hit rate when deciding (10/15 · coverage 9.38%)</span><strong>66.67%</strong></div> <div class="bar-track"><div class="bar-fill bar-fill--amber" style="width:66.7%;"></div></div> </div> <div class="score-metric"> <div class="score-metric__head"><span>3-class accuracy (36 of 46 are abstentions)</span><strong>28.75%</strong></div> <div class="bar-track"><div class="bar-fill bar-fill--rose" style="width:28.75%;"></div></div> </div> </div> </div> <div class="score-row"> <div class="score-rowtop"> <span><strong>Trivial baseline: always answer "Undefined"</strong></span> <span><code>0.00 GiB</code> · <code>0 ms</code> · <code>0</code> FP</span> </div> <div class="score-bars"> <div class="score-metric"> <div class="score-metrichead"><span>Hit rate when deciding (coverage 0.00%)</span><strong>N/A</strong></div> <div class="bar-track"><div class="bar-fill" style="width:0%;"></div></div> </div> <div class="score-metric"> <div class="score-metric__head"><span>3-class accuracy (40/160 free hits)</span><strong>25.00%</strong></div> <div class="bar-track"><div class="bar-fill bar-fill--cyan" style="width:25.0%;"></div></div> </div> </div> </div> </div> --- Research takeaways: which open model could run in milliseconds on my i7-8550U When would a JEV-style classifier committee actually make sense? When each judge clears 50% accuracy on every class out-of-sample (Condorcet 1785[^condorcet1785]), when their errors are uncorrelated (Dietterich 2000[^dietterich2000]), when their probabilities are properly calibrated (Guo et al. 2017[^guo2017]), and when at least two judges have real sensitivity to vote "No". Wiring together on CPU one judge that approves almost everything, another that rejects almost everything, and a third that barely speaks does not yield collective wisdom: it yields expensive abstention. That is why I retired the prototype. Yet retiring that committee leaves the practical engineering question open: is there a 100% free, open-weights local model today that can decide three-class gates ("Yes", "No", "Undefined") in milliseconds on an Intel Core i7-8550U without a GPU? I believe so, provided I switch architectural families and stop treating logical verification as a text-generation problem; but that is a hypothesis this experiment did not test. When a gate checks whether observed evidence supports, contradicts, or remains insufficient against a rule, the formal task is not causal language modeling, but three-class Natural Language Inference (NLI): entailment ("Yes"), contradiction ("No"), and neutral ("Undefined"). In that category, the candidate I propose to measure next is cross-encoder/nli-deberta-v3-small, built on the DeBERTaV3 architecture (He, Gao, and Chen 2023[^he2023]); its repository also ships an ONNX INT8 build for AVX2 CPUs that runs with onnxruntime, and optimum can export others. The idea of reusing an NLI model as a classifier comes from Laurer et al. (2024[^laurer2024]), whose model family includes a larger variant, MoritzLaurer/DeBERTa-v3-base-mnli-fever-anli. I have not yet measured either one on my 160-case bank: <div class="nli-solution-card" role="region" aria-label="Technical specification of the open model I propose to measure on CPU: cross-encoder/nli-deberta-v3-small in ONNX INT8"> <div class="nli-solution-cardtop"> <h3 class="nli-solution-cardtitle">Hypothesis to measure on CPU: nli-deberta-v3-small (ONNX INT8)</h3> <div class="jev-chips"> <a class="jev-chip" href="huggingface.co" target="_blank" rel="noopener">HF Model (Apache)</a> <a class="jev-chip jev-chip--amber" href="arxiv.org" target="_blank" rel="noopener">DeBERTaV3 Paper</a> <a class="jev-chip" href="onnxruntime.ai" target="_blank" rel="noopener">ONNX Runtime</a> </div> </div> <p class="nli-solution-carddesc"> Bidirectional <em>cross-encoder</em> with <strong>disentangled attention</strong> (separating content and relative position) pre-trained via <em>replaced token detection</em> (ELECTRA) and fine-tuned on <code>SNLI</code> + <code>MultiNLI</code>. It evaluates premise and hypothesis jointly in a single forward pass without loading PyTorch. </p> <div class="nli-solution-cardgrid"> <div class="nli-solution-cardmetric"> <strong>Latency still to be measured</strong> I did not run it on this bank. Because it decides in a single pass without generating text, my hypothesis is that it will land well below the committee's <code>366–1,717 ms</code> warm and <code>~31.7 s</code> cold. </div> <div class="nli-solution-cardmetric"> <strong>~165 MiB on disk (ONNX INT8 for AVX2)</strong> <code>44M</code> backbone parameters (<code>142M</code> total with vocabulary embeddings); the <code>model_quint8_avx2.onnx</code> file takes about <code>165 MiB</code> on disk. Its runtime RAM is still to be measured, so I do not yet compare it with the roughly <code>7.8 GiB</code> of RAM used by the three judges. </div> <div class="nli-solution-card__metric"> <strong>3 native classes ("Yes" / "No" / "Undefined")</strong> Emits direct logits for <code>contradiction</code>, <code>entailment</code>, and <code>neutral</code> (<code>87.55%</code> on MNLI <em>mismatched</em>, according to its model card). Whether that fixes the <code>"No"</code> blindness (<code>0/60</code>) on my gates remains to be measured. </div> </div> </div> The takeaway I keep from this proof of concept has a measured part and an unmeasured one. Measured: on a work laptop without a dedicated accelerator, a committee of mismatched models did not beat its best individual judge on three-class accuracy and never managed to say "No". Still a hypothesis: that a single small NLI cross-encoder, calibrated and compiled to ONNX INT8, would beat it in latency, memory footprint, and sensitivity to say "No". When verification is deterministic (a hash, a JSON schema, or an exit code), a 0 ms code rule remains unbeatable; and when I genuinely need to judge semantic entailment or contradiction locally, my next step is not to stack three judges in series, but to measure an architecture designed for that task first. --- References [^arc532025]: Arc53. 2025. "arc-decide-0.4b-v0.2: Compact ONNX Decision Classifier". Hugging Face model repository. huggingface.co. [^browseruse2026]: Browser Use and TypeSafe AI. 2026. "JEV Ultrafast: Sub-Second Browser Agent Actions with Jev Decision Models". Official GitHub repository. browser-use/jev-ultrafast. [^condorcet1785]: Condorcet, Jean-Antoine-Nicolas de Caritat, Marquis de. 1785. Essai sur l'application de l'analyse à la probabilité des décisions rendues à la pluralité des voix. Paris: Imprimerie Royale. [^dietterich2000]: Dietterich, Thomas G. 2000. "Ensemble Methods in Machine Learning". In Multiple Classifier Systems (MCS 2000), Lecture Notes in Computer Science, vol. 1857, 1–15. Berlin: Springer. Scholar [^guo2017]: Guo, Chuan, Geoff Pleiss, Yu Sun, and Kilian Q. Weinberger. 2017. "On Calibration of Modern Neural Networks". In Proceedings of the 34th International Conference on Machine Learning (ICML), PMLR 70: 1321–1330. [^he2023]: He, Pengcheng, Jianfeng Gao, and Weizhu Chen. 2023. "DeBERTaV3: Improving DeBERTa using ELECTRA-Style Pre-Training with Gradient-Disentangled Embedding Sharing". In International Conference on Learning Representations (ICLR 2023). arXiv · Scholar [^laurer2024]: Laurer, Moritz, Wouter van Atteveldt, Andreu Casas, and Kasper Welbers. 2024. "Less Annotating, More Classifying: Addressing the Data Scarcity Issue of Supervised Machine Learning with Deep Transfer Learning and BERT-NLI". Political Analysis 32 (1): 84–100. Model from the same family: huggingface.co. DOI · Scholar [^nandhakishorm2026a]: NandhaKishorM (ConvAI Innovations). 2026a. "Laya: System 1 Non-Autoregressive Multilingual Decision Engine". GitHub repository. NandhaKishorM/laya. [^nandhakishorm2026b]: NandhaKishorM. 2026b. "VegaML: Potential-Well Physics Decision Engine over Frozen Language Backbones". GitHub repository. NandhaKishorM/vegaml.
PDF ஒரு இடம், EPUB வேறு இடம், Kindle-ல் திறக்க முடியாது.. Calibre இதை முடிக்கிறது. இலவச ebook manager, எல்லா format-களையும் அடுக்கி Kindle-க்கு மாற்றித் தருகிறது. முதலில் எதை அடுக்குவீர்கள், பாடப் புத்தகங்களையா, நாவல்களையா ? kovidgoyal/calibre Instagram-லும் பின்தொடருங்கள்: instagram.com
Financial Times broken? Just downloaded latest version. FT updated so that they have a stricter structural paywall that completely blocks automated scripts, scraping tools, and RSS readers. However, I used to be able to get free articles etc. Out of the box, it simply doesn't work. Even modifying the python as per the note, doesn't fix. Anyone got a workaround? github.com/kovidgoyal/calibre/blob/master/recipes…
TUIアプリを作る時に取り入れてみたいターミナルの機能とUI/UX はじめに TUIアプリを開発する時に対応してみたいターミナルの機能やUI/UXをまとめました。 主にOpenTUIのReact APIとprintfコマンドで紹介します。TSXのコードは、コンポーネント内で使う部分を抜粋しています。 ! 今回紹介する機能は、ターミナルやその設定によって対応状況が異なります。筆者は主にkittyやGhosttyを用いています。 また、調べきれていない部分や間違っている部分もあるかもしれないのでご了承ください。 文中のOSCやCSIは、色やタイトルなどを操作・問い合わせするために、ターミナルへ送る制御列です。printfの例にある\033はESC文字、\007はBEL文字を表します。 機能とUI/UX レスポンシブデザイン ターミナルでもWebなどと同じように、実行中に画面サイズが狭くなったり広くなったりします。 幅に応じて横並びを縦並びにしたり、サイドバーを必要な時だけ開く形にしたりすると、小さい画面でも操作しやすくなります。 OpenTUIでは、以下のように幅と高さを取得できます。画面サイズが変更された場合も、自動的に値が更新されます。単位はピクセルではなく、文字の列数・行数です。 import { useTerminalDimensions } from "@opentui/react" const { width, height } = useTerminalDimensions() const compact = width < 80 Dark/Lightテーマ ターミナルやOSのDark/Lightに合わせて、TUIのテーマを切り替えることができます。 対応するターミナルでは、以下の問い合わせでDark/Lightの設定を取得できます。 printf '\033[?996n' 応答が CSI ?997;1n だったらDark 応答が CSI ?997;2n だったらLight 応答はターミナルからの入力として返るので、アプリ側で受信する必要があります。シェルで実行すると、入力行に応答が現れる場合があります。 また、CSI ?2031hを送ると配色変更の通知を有効にでき、OSの外観を切り替えた時などに追従できます。終了時はCSI ?2031lで解除します。問い合わせと変更通知の仕様 Ghosttyでターミナルの配色自体をOSに連動させたい場合は、明暗両方のテーマを設定します。Ghosttyのテーマ設定 theme = dark:Catppuccin Frappe,light:Catppuccin Latte OSC 11で既定の背景色を取得し、その明るさからDark/Lightを推定する方法もあります。ただし、これは配色からの推定なので、OSの外観設定と同じとは限りません。 太字/下線/斜体などの文字装飾 文字は太字・下線・斜体に加え、取り消し線・薄字・反転・点滅などで装飾できます。 強調したい部分を太字にする、補足を薄字にする、削除済みの項目に取り消し線を付ける、といった使い方ができます。点滅の表示はターミナルや設定によって異なります。 import { bold, dim, strikethrough, t } from "@opentui/core" const text = t${bold("重要")} ${dim("補足")} ${strikethrough("削除済み")} return <text content={text} /> opentui.com 前景色/背景色 前景色は主に文字の色、背景色はその後ろの地の色です。 OSC 10でターミナルの既定の文字色、OSC 11で既定の背景色を変更できます。ただし、アプリが個別に赤や青などを指定した部分は、その指定色を使います。 OpenTUIでターミナルの既定色を使って描く場合は、以下のように指定できます。 import { RGBA } from "@opentui/core" return <box backgroundColor={RGBA.defaultBackground()}> <text fg={RGBA.defaultForeground()}>ターミナルの既定の文字色で表示</text> </box> RGBA.defaultForeground()などは、ターミナルへ問い合わせてRGB値を取得する関数ではありません。「ターミナルの既定色を使う」という指定です。実際のRGB値が必要なら、await renderer.getPalette()のdefaultForeground / defaultBackgroundを参照します。OpenTUIの色の扱い ANSI 16色パレット ANSI 16色パレットは、通常色8色と明るい色8色からなる、色番号0〜15のパレットです。色のRGB値そのものはターミナルの設定やテーマによって変わります。 成功・エラー・警告などの役割に色番号を割り当てると、利用者のターミナルテーマに合わせたUIにできます。例えば、次のように使えます。 import { RGBA } from "@opentui/core" return <box> <text fg={RGBA.fromIndex(2)}>✓ 保存しました</text> <text fg={RGBA.fromIndex(1)}>× 接続に失敗しました</text> <text fg={RGBA.fromIndex(3)}>! 変更が未保存です</text> </box> 入力カーソル 文字の入力位置を示すカーソルは、形状や点滅、色を変更できます。 ターミナルの制御列では、形状はDECSCUSR、色はOSC 12を使います。 OpenTUIでは、次のように指定できます。 return <input placeholder="ここに入力" cursorStyle={{ style: "line", blinking: true }} cursorColor="#ff8f8f" /> 入力モードを形で区別したり、背景に埋もれない色にしたりすると、入力位置を見つけやすくなります。 クリップボード コードブロックやコマンドの横に「コピー」ボタンがあると、文字をドラッグして選択する手間を減らせます。 OSC 52を使うと、ターミナルを経由してOSのクリップボードへ文章を渡せます。 import { useRenderer } from "@opentui/react" const renderer = useRenderer() const copy = () => renderer.copyToClipboardOSC52('console.log("Hello!");') クリップボードへの書き込みを許可するかはターミナルの設定に依存します。OpenTUIのクリップボード ポインタ形状 マウスを重ねた場所に応じて、ポインタの形を変えられます。ボタンではpointer、文章の上ではtext、横幅を変えられる境界ではew-resizeといった使い方ができます。 OpenTUIではsetMousePointer()で指定します。ターミナルへ送る制御列はOSC 22です。 import { useRenderer } from "@opentui/react" const renderer = useRenderer() const setPointer = (style: "pointer" | "default") => { renderer.setMousePointer(style) renderer.requestRender() } return <box onMouseOver={() => setPointer("pointer")} onMouseOut={() => setPointer("default")} > <text>マウスを重ねてみる</text> </box> 形状名はCSSのcursorに近いものですが、表示できる種類はターミナルによって異なります。kittyのポインタ形状の仕様 ハイパーリンク OSC 8を使うと、URLとは異なる文字列をリンクとして表示できます。ファイル名や「ドキュメントを開く」といったラベルに、リンク先を持たせられます。 OpenTUIでは<text>の中に<a>を置きます。 return <text> <a href="example.com"><u>ドキュメントを開く</u></a> </text> リンクの開き方はターミナルによって異なります。GhosttyのmacOS版では⌘クリック、kittyではCtrl+Shiftクリックなどです。通常クリックがTUI側の操作になる場合もあるので、操作方法やコピー用のURLも案内しておくと分かりやすそうです。Ghosttyの設定、kittyの設定 タイトル ウィンドウやタブのタイトルに、アプリ名や作業中の内容を表示できます。複数のターミナルを開いている時に見分けやすくなります。 OSC 2はタイトル、OSC 1はアイコン名、OSC 0はその両方を指定します。 OSC 0: 両方設定 printf '\033]0;Hello OSC 0\007' OSC 1: アイコン名のみ設定 printf '\033]1;Hello OSC 1\007' OSC 2: ウィンドウタイトルのみ設定 printf '\033]2;Hello OSC 2\007' ここでいう「アイコン名」は文字列のラベルで、画像アイコンを設定するものではありません。現行のkittyやGhosttyでは、OSC 1によるアイコン名の変更が実装されていません。GhosttyではOSC 0はOSC 2相当として扱われます。 iTerm2では、OSC 1でタブのタイトル、OSC 2でウィンドウのタイトルを変更できます。ただし、実際の表示は設定によって異なります。 デスクトップ通知 長い処理の完了や、確認待ちになったことをOSの通知で知らせられます。別のアプリへ移動している時にも気づくことができます。 kittyのOSC 99、iTerm2系のOSC 9、その他OSC 777など、通知はターミナルごとに方式が異なります。 OpenTUIでは以下のように通知を要求できます。 import { useRenderer } from "@opentui/react" const renderer = useRenderer() const notify = () => renderer.triggerNotification("処理が完了しました", "TUIアプリ") triggerNotification()の戻り値のtrueは、通知要求を送信できたことを表します。実際にOSへ表示されるかは、ターミナルやOSの通知設定、フォーカス状態などにも依存します。OpenTUIの通知 ローディング表示と進捗表示 対応するターミナルではタブやタスクバーなどに進捗を表示できます。進捗率が分からない処理、進捗率が分かる処理、エラー、一時停止をそれぞれ表せます。 OSC 9;4を使うと、次のように進捗状態をターミナルへ通知できます。 printf '\033]9;4;3\007' # 進捗率不明のローディング printf '\033]9;4;1;50\007' # 通常の進捗: 50% printf '\033]9;4;2;50\007' # エラー状態: 50% printf '\033]9;4;4\007' # 一時停止 printf '\033]9;4;0;0\007' # 表示を解除 Ghosttyでは約15秒間更新がないと進捗表示が自動的に解除されるため、長時間の処理では定期的な更新が必要です。 表示場所や見た目はターミナルによって異なります。 ドラッグ&ドロップ ファイルやテキストをターミナルへドラッグ&ドロップできます。 ファイルパスを文字列として貼り付ける方式のほか、MIME形式でデータをやり取りするOSC 72という拡張もあります。OSC 72では、TUIからほかのアプリへのドラッグにも対応しています。kittyのDrag and Dropプロトコル ファイルの一覧がtext/uri-listで届いた場合は、例えば次のようにパスへ変換できます。 import { fileURLToPath } from "node:url" fileURLToPath("file:///Users/me/My%20File.txt") // → /Users/me/My File.txt OSC 72の利用にはデータの受信・取得などの処理が必要で、対応するターミナルも限られます。 画像表示 サムネイルや画像のプレビューもターミナル内に表示できます。大きく分けると、次の2つの描き方があります。 Kitty GraphicsやSixelなど、ターミナルの画像表示プロトコルを使う方法 色付きのUnicodeブロック文字を並べて、セル単位で画像を表現する方法 OpenTUIではprotocol="auto"にすると、対応状況に応じてKitty、Sixel、Unicodeブロックから描画方式を選びます。 return <image source="./sample.png" protocol="auto" fit="fit" style={{ width: 40, height: 12 }} /> ブロック文字による描画は細部が粗くなりますが、画像プロトコルが使えない場合の代替にもなります。 opentui.com Nerd Fontsとアイコン Nerd Fontsは、開発ツールやファイル種別などのアイコンを追加したフォントです。ターミナル側で対応するフォントを選ぶと、文字としてアイコンを表示できます。 return <text>{"\uE0A0"} main</text> グリフを含まないフォントだと表示が欠ける場合があるので、アイコンだけに意味を持たせず、文字ラベルも添えておきたいです。 nerdfonts.com ターミナル内3D 立方体などを回転させて、ターミナルのセルへ描くこともできます。 OpenTUIには、Three.jsのWebGPUレンダラーをOpenTUIのバッファへ接続する@opentui/threeもあります。こちらはBunやWebGPUを利用するため、実行環境の対応が必要です。 opentui.com 取り入れるときに考えておきたいこと マウス操作だけでなく、Tab・矢印・Enterなどのキーボード操作も用意する 色やアイコンに加えて、文字ラベルや記号でも状態を伝える 未対応の場合に備えて、手動コピーやURL表示などの代替を用意する 変更したターミナルの配色やカーソルを終了時に元に戻し、進捗表示なども解除する おわりに 今回は、TUIアプリで対応してみたいターミナル機能やUI/UXについて紹介しました。 小さい工夫でも、情報を見分けやすくなったり操作が楽になったりするので、用途に合うものから取り入れてみてください!
两百本书塞进 calibre,手机随时翻还能听! calibre 建库转格式,calibre-web 手机浏览器直接读,Ebook-Translator 一键译中文,ebook2audiobook 转有声书,OpenComic 管漫画。全免费。 kovidgoyal/calibre
终端窗口太多,来个能分屏的。🐈 kitty 支持标签页、分屏和图片显示,键盘操作也方便。适合 Linux、macOS 开发。⌨️ kovidgoyal/kitty #Terminal #浇朋友 #蓝朋友 #互关 #fo
Can someone with infinite claude try to implement the kitty daemon as discussed here I'd love to have a kitty server running so even if I close the ui the processes keep working. Esp for ssh. And I don't like other options like dtach or whatever. In fact I am not looking for other solutions so it's a request don't recommend me one. I just want someone with claude subscription to try to implement the daemon
Calibre 是 Kovid Goyal 维护的开源电子书管理工具。 支持多种格式互转,也能开内容服务器,家里浏览器能进书库。 免费,全平台。带 DRM 的书它不转。 🔗kovidgoyal/calibre