JC Davis

The platform

Dottie


An orchestration platform built around a measured loop. Goals go in, one router sends each to the cheapest tier that can do the work, and every run leaves a measured trace.

github.com/jcdavis131/dottie

One monorepo

Dottie is the whole platform in one repository: the harness, the router, the decision model, the local sidecar and the sites around them. Four parts carry the story.

  • The CLI

    scout

    The harness's front door. One entry point, plugins behind it.

    apps/scout-cli

  • The policy

    The router

    One routing policy that picks a tier for each goal.

    packages/dottie-loop

  • The model

    System One

    Typed questions, answered as Choice, Score and Noul.

    apps/jev-v0

  • The sidecar

    dottie-os

    Serves System One at /decide on your machine.

    local · tailnet

The loop the parts serve. Every step writes down what it measured.

  1. Route
  2. Execute
  3. Record
  4. Mine
  5. Retrain
  6. Gate
  7. Serve

apps/scout-cli

scout

Dottie's command line. The harness gets exactly one tool, and every capability is a plugin behind scout --json, each declaring what it may touch.

  • 60+ plugins, one entry pointHarness, MCP, forge, vector and more, each a subcommand.
  • Default denyEvery plugin declares network, filesystem and secrets in a manifest. Undeclared means refused.
  • Real tool callsA goal like mcp:<server>__<tool> runs a real external call through the meta-MCP layer, under an allowlist.
  • Measured runsharness run records latency, status and token cost for every step. Zero is written down as a measured zero.

Install with uv

$ git clone https://github.com/jcdavis131/dottie.git
$ cd dottie
$ uv sync --all-groups --frozen
$ uv run scout --help

# route a goal with the deterministic heuristic
$ uv run scout --json harness route \
    "compare Stripe vs Lemon Squeezy Aug 2026"

# route, plan, execute, write the measured timeline
$ uv run scout harness run "ship the harness loop" --json

# serve scout itself as one MCP server
$ uv run scout mcp serve

The standalone scout-cli repository is superseded; scout lives in the monorepo at apps/scout-cli.

packages/dottie-loop · router.py

The router

One routing policy chooses among five tiers, from deterministic to agentic epic. A goal passes through four gates, in order, on its way to a tier.

The router's decision order, drawn as frames receding to one point Four nested frames. The outer frame, 01, is hard constraints. Inside it, 02, the heuristic, drawn in the accent colour because it is authoritative today. Inside that, 03, the learned recommendation, dashed because it only applies when the checkpoint has passed the gate. Innermost, 04, escalation, dashed because it only happens after a recorded insufficiency. The vanishing point is the chosen tier. 01 02 03 04 Goal Tier
Always applied Only under a condition Authoritative today
  1. 01

    Hard constraints

    Policy exclusions first. Restricted goals are not routed automatically, and nothing runs when neither a model nor a tool is available.

  2. 02

    Heuristic

    Deterministic when it can satisfy the goal, otherwise the heuristic tier. Always available, and it has the final word today.

  3. 03

    Learned, if gated

    A learned answer counts only if its artifact says gate_passed: true, a human stamped it, and it picks an equal or cheaper tier.

  4. 04

    Escalate, if recorded

    A more capable tier only after a recorded insufficiency: when it happened and what failed. Never on a hunch.

Three backends, one policy
BackendWhat it isToday
HeuristicMoMA-lite rules over the goal text and its side effects.Authoritative
Learned MLPThe orchestrator model from the training factory, apps/ava-factory.Advisory
System OneA typed question sent to dottie-os over /decide.Advisory
  • Advisory means logged and shownLearned and System One answers are recorded next to the heuristic's and displayed. They do not change the tier until a checkpoint passes the gate and a human stamps it.
  • The last recorded comparisonIn the latest evaluation report (August 2026), the learned candidate and the heuristic both scored 83.6% on 61 measured held-out goals. A tie does not pass the gate, which requires strictly beating the heuristic, so the heuristic stayed.
  • Traces feed the next modelscout and jarvisd now route through this one policy, and every routed goal is recorded as a trace. Real traces feed the training loop (scout router pack, train, eval, promote), which runs on the GPU host.

Contract · jev-decision-schema-1.0.0

System One

The decision model. It takes state and a set of typed questions and answers each with a closed distribution, never free text. Three question types, frozen in one schema.

The three frames below are what /decide returns today with no checkpoint loaded: mode: untrained, uniform over the offered options. The shapes are the contract. The numbers are exactly what an untrained model owes you.

  1. One of a closed set

    Choice

    .333 .333 .333 billing technical other
    choice
    billing
    shape_concentration
    0.333

    Pick one label from 2 to 255 named options. On a perfect tie the first key wins, and the probabilities say it was a tie.

  2. A level on an ordered scale

    Score

    .25 .25 .25 .25 none minor major blocking 1.5
    score
    1.5
    shape_concentration
    0.25

    Place the state on a rubric of 2 to 10 named levels. The score is the expected level, with a legend back to the words.

  3. Yes or no, as a number

    Noul

    0.5 0 · no 1 · yes
    noul
    0.5
    shape_concentration
    n/a

    A yes-or-no question answered as one probability of yes, between 0 and 1. The number is the whole answer.

shape_concentration

maxᵢ p(optionᵢ)

The largest probability in a Choice or Score answer. It describes the shape of the distribution: 1/n when the model spreads evenly over n options, 1 when all the mass sits on one. It is a named statistic, not a promise about accuracy, so System One never calls it confidence and makes no calibration claim.

The local sidecar

dottie-os

dottie-os serves System One on your own machine or tailnet. Tools ask it a typed question over POST /decide and get typed answers back. Nothing is published to a public host.

Your machine · tailnet scout router /decide dottie-os 127.0.0.1:8770
  • Loopback by defaultThe reference server binds 127.0.0.1:8770 unless told otherwise. Reach it over your tailnet, not the open internet.
  • Refuses rather than guessesEvery request is checked against the frozen schema: 1 to 32 questions, at most 64 KB. A schema violation is a 422, an oversized body a 413; nothing is silently truncated.
  • Where it livesThe reference /decide server is apps/jev-v0. The sidecar runs on the GPU host; apps/dottie-os in the repo mirrors its data-curation scripts.

Request · POST /decide

{
  "schema": "jev-decision-schema-1.0.0",
  "state": {
    "ticket": "TD-1001",
    "message": "Charged twice on invoice 4412."
  },
  "questions": {
    "team": {
      "type": "choice",
      "instructions":
        "Which team should handle this ticket?",
      "criteria": {
        "billing": "Charges, invoices, refunds",
        "technical": "Bugs, outages, integrations",
        "other": "None of these"
      }
    },
    "urgent": {
      "type": "noul",
      "instructions":
        "Does the sender ask for help today?"
    }
  }
}

Response · untrained, rounded

{
  "schema": "jev-decision-schema-1.0.0",
  "model": "jev-v0-untrained",
  "mode": "untrained",
  "answers": {
    "team": {
      "type": "choice",
      "choice": "billing",
      "probabilities": {
        "billing": 0.333,
        "technical": 0.333,
        "other": 0.333
      },
      "shape_concentration": 0.333
    },
    "urgent": { "type": "noul", "noul": 0.5 }
  }
}

Designed · not built

The hive

A way to run a team of agents on plain files next to the sidecar: a roster, a shared blackboard, a task ledger, mailboxes and append-only logs. No database; everything readable with cat. It exists today as a design, not as code.

  • One writer per fileEach agent writes only inside its own directory. One process commits to git; agents never do.
  • Fail-closed deliveryA router moves messages from one outbox to another inbox. Undeliverable mail bounces to the orchestrator; malformed mail is quarantined and logged, never dropped.
  • A human at the boundaryPause, gate, steer and halt are enforced where actions leave the hive. Destructive operations need an explicit confirmation.

hive/ · the planned layout

hive/
  registry.json   # roster: agent, role, capabilities
  board.md        # shared blackboard, one scribe
  tasks.json      # task ledger
  log.jsonl       # append-only event feed
  costs.jsonl     # append-only cost ledger
  agents/<id>/
    identity.md   # who I am, what I may do
    memory.md     # long-term memory
    inbox/        # delivered to me
    outbox/       # waiting for the router
    cursor.json   # nothing is read twice

As of September 2026

Status

What runs, what is being built, and the rules that do not bend while it is.

Shipped

  • scoutThe CLI in the monorepo: harness route and run, meta-MCP, forge, 60+ plugins.
  • The heuristic routerMoMA-lite over five tiers, authoritative in the harness.
  • The System One contractFrozen jev-decision-schema-1.0.0 and a typed /decide server.
  • Gates as codedottie-loop: evaluation gates, promotion and rollback records that can stop an advance.
  • One routerA single policy in dottie-loop for scout and jarvisd, with heuristic, learned MLP and System One backends. The heuristic decides; the others are advisory.
  • The consoleos.jcamd.com: Conductor and Pair for dottie-os. They show offline until paired with a running jarvisd.

In progress

  • System One checkpointsA small model with LoRA and pointer heads. None has passed the gate.
  • The training loopThe commands are in; the first training run on real traces happens on the GPU host.
  • The hiveDesigned; not yet built.

The rules

  • Nothing auto-promotesA checkpoint is authoritative only if its artifact says gate_passed: true and a human stamped it.
  • No synthetic championsSynthetic rows never train a champion. Router training data is real harness traces only.
  • No calibration claimsProbabilities are named for what they are: shape_concentration, backend_confidence.
  • No champion without a measurementA model is called live only when it has been measured.

Source

Everything above is in one repository.

MIT licensed, solo, built on public and free-tier tools. Read the code; when this page and the code disagree, the code is right.