DevCentr agent harness (Hornet)

DevCentr is building Hornet — a lightweight agent harness (working name aligned with harness; hornets swarm, which matches parallel actor nodes).

Hornet is not a Cursor-class IDE. It is a focused local runtime that consumes the same harness-neutral stack as Cursor, Claude Code, Hermes, and T3code.

In plain language: Hornet shell + Mixr model routing + shared rules layer + D tooling from dlang-supplemental.

When HARNESS_NAME = hornet on a workstation, $CODE_ROOT/harness.md records Hornet-specific discovery paths and UX contracts (token provenance, actor-model UI, Mixr routing).

Hornet and Mixr

Name Role

Hornet

The harness — chat, tools, project context, node graph on disk, grid/fork/timeline views

Mixr

Meta-agent / model router (Cursor Auto-shaped) — picks which model runs each node or job

Coordinator

Top-level actor in the node graph; may delegate routing decisions to Mixr before spawning task nodes

A single default model (for example GLM on OpenRouter) does not scale across the swarm. Different nodes need different tradeoffs:

  • Coordinator / metathread — long context, strong summarization, user-facing voice

  • Task nodes — coding-capable, tool-use reliable, cost-bounded for parallel grid work

  • Disambiguation — small, fast, cheap — boundary resolution only

  • Mixr itself — tiny router call; classifies intent and emits a route plan before the heavy model runs

Mixr reads node type, declared job, token budget, user BYOK keys, and org policy, then assigns { model, provider, maxTokens, reason } per invocation. The route plan is logged in orchestrator/meta.jsonl for audit — same spine as spawn refs.

Users may override a route on a node; Mixr learns from overrides only in explicit feedback paths (not silent drift).

Proposed harness variables (Hornet + Mixr):

HARNESS_NAME = hornet
MIXR_ROUTING = on | off
MIXR_ROUTER = on-device | api | auto
MIXR_ROUTER_BASE_URL = http://127.0.0.1:11434/v1
MIXR_ROUTER_MODEL = <local OpenAI-compat router model>
MIXR_ROUTER_RAM_MIN_MB = 2048
MIXR_DEFAULT_POLICY = balanced | cheap | quality | byok-only
MIXR_SUPPRESS_PROVIDERS = anthropic,...
MIXR_SUPPRESS_MODELS = ...
MIXR_ALLOW_SUPPRESSED = off | explicit-only

When MIXR_ROUTING=off, Hornet falls back to a single pinned model per node type in harness config — useful for debugging, not the production default.

Default Mixr placement is on-device: classify via a local OpenAI-compatible server. API failover happens when RAM is below MIXR_ROUTER_RAM_MIN_MB or the local server is unreachable. Anthropic is suppressed by default — automatic routes never select it unless the user explicitly overrides.

Detail: Mixr routing and cost. Speculative validation: Shadow workspace and LSP.

Implementation

Reference runtime: dev-centr/hornet (D + tgc).

Phase Ships in Hornet

v0

$CHAT_ROOT disk layout, spawn API, metathread refs, CLI (hornet init, spawn, message)

v1

Mixr routing, wait-graph, HTTP desk (hornet serve), grid + fork web UI

v0.5+

On-device Mixr + suppress lists; OpenAI-compat + /api/provider/* seams for t3code HornetDriver

v2

Temporal layout engine — scrubber, fade, heatmap, scoped bookmarks (/api/temporal)

cd $env:code\github.com\dev-centr\hornet
dub build
.\hornet.exe init .\my-chat
.\hornet.exe serve .\my-chat --port 8765

Why a harness at all

dev-centr/agent-rules already separates forkable policy from machine-local wiring (harness.md, machine.md).

That stack answers how rules travel.

It does not answer which runtime executes them on a machine that wants something lighter than a full IDE agent.

Design direction

Principle Meaning

Light, not monolithic

T3code-shaped footprint — chat, tools, project context — without duplicating DevCentr’s existing specialized tools

Harness-neutral consumption

Same user.md, org AGENTS.md, skills, and $CODE_ROOT/harness.md variables as other harnesses

Ecosystem, not kitchen sink

Strip duplicate features that already live in sibling orgs (HCI Nerdz surfaces, Desktop-Tooling OS utilities, dlang-supplemental native libs)

Steer upstream, integrate locally

Open-source harnesses may receive submissions; DevCentr integration still strips overlap and wires org-specific infrastructure

dlang-supplemental native core

Prefer D libraries and tooling from dlang-supplemental over reimplementing helpers in TypeScript or Rust

Swarm by default

Actor-model node graph + Mixr routing — parallel agents are first-class, not an IDE afterthought

Relationship to T3code

T3code is listed in harness-neutral architecture as a harness enum value (HARNESS_NAME = t3code).

Division of labor:

  • t3code owns multi-machine registration/sync (laptop client ↔ desktop server) and the mature control surface.

  • Hornet owns Mixr, the disk node graph, tools, and (planned) shadow/LSP validation.

  • HornetDriver (in a t3code fork / eventual upstream PR) is the provider adapter that lets t3code drive Hornet the way it drives Cursor, Claude, Codex, or OpenCode.

While Hornet’s own remote desk is thin, expose Hornet via hornet serve and select the Hornet provider in t3code settings (serverUrl, default http://127.0.0.1:8765). Machine sync stays t3code’s; Hornet does not reinvent pairing.

There is no DevCentr-owned t3code org fork — personal fork work is fine for the driver; steer upstream when the protocol stabilizes.

Token provenance (first UX contract)

The first cross-org UX contract wired into harness metadata is token provenance from HCI Nerdz:

Harness variable (proposed):

TOKEN_PROVENANCE = emit-spans | consume-spans | off

When emit-spans, the runtime attaches provenance metadata the chat renderer can style without rereading tool logs.

Actor-model agentic UI (second UX contract)

The second cross-org UX contract is actor-model agentic UI from HCI Nerdz — a persisted node graph where each node is an actor (bounded chat context with a type, disk address, spawn lineage, and mailbox summary).

Linear chat drifts; agent work spawns tangents and parallel jobs. The harness records nodes on disk (graph.json, nodes/{id}/meta.json, nodes/{id}/chat.jsonl). Parent nodes record child addresses in spawned[]; children record spawnedBy. When chat drifts off-topic, spawn a child node instead of polluting the parent transcript.

The task grid is one projection — filter type=task for parallel repo work. Discussion nodes spawn task nodes; task tangents spawn discussion children.

Harness variables:

ACTOR_AGENTIC_UI = graph-grid | serialized | off
ACTOR_GRAPH_EPOCHS = on | off
ACTOR_WAIT_GRAPH = warn | enforce | off
ACTOR_NODE_STORE = jsonl-per-node | off

When graph-grid (defaults: ACTOR_NODE_STORE=jsonl-per-node, ACTOR_WAIT_GRAPH=warn):

  • Node graph persisted under $CHAT_ROOT/; per-node chat.jsonl authoritative; orchestrator metathread with line refs

  • Model-proposed spawn on drift; disambiguation node when topic boundary is unclear

  • Grid shows task nodes; fork panel loads nodes/{id}/chat.jsonl

  • Coordinator thread is continuous with summarization; hierarchical and global-context modes are views over the same store

  • Temporal layout (planned) — reusable timeline widget with global and per-node scopes

Full spec: Actor-model agentic UI. Deprecated alias: Project inbox (renamed).

What this is not

  • Not a Cursor replacement — Cursor remains a valid HARNESS_NAME

  • Not a rules fork — policy stays in dev-centr/agent-rules

  • Not a grab-bag of every OSS agent feature — duplicates are stripped at integration time