Trove parts

The parts of Trove, the door that reaches them, and who writes their state

Trove runs Claude Code sessions as an unattended work engine: each session works in its own git worktree, and you finalize the result to the default branch. This page explains how Trove is cut into parts, how a program outside the Hub reaches them, how a recurring spec uses them, and why one process writes all of their state.

One part, one job

Each part of Trove does one thing, keeps its own store, and has its own OPAL task family:

Part Its job Task family
Specs Stores structured specs and their work units, with history and leases spec.*
Worktrees Keeps many named worktrees on one checkout worktree.*
Sessions Runs LLM sessions and records their turns session.*
Builds Builds and tests, admitted by the machine's kiln broker build.*
Placement Decides where a job runs: here, later, or on another node fleet.*, batch.*

A part depends only on the libraries below it, never on a sibling. Where one part needs the work of another, Trove passes it in. For example, the worktrees part knows git and nothing about Claude Code: when Trove creates a worktree for a session, the sessions part writes the session's CLAUDE.md and hook configuration into it, and the worktrees part keeps those files out of git.

The door

The door is the one local endpoint of your user on your computer that answers OPAL calls from outside the app. A Claude Code session in a terminal, or a tool you run, calls a task through the door and gets the result. There is no network listener: a remote node reaches the parts over the node's own comms.

The door lives in a folder of your user only:

  • <runtime folder>/octomy-door/ where the system gives each user a runtime folder, as /run/user/<uid> on Linux.
  • <cache folder>/octomy-door/ where it does not, as on Windows.

The folder holds door.lock, door.json and, where local sockets are files, door.sock. door.json names the endpoint, a token that is new at each start, the process and the identity that the door serves. Only your user can read it, and the token is how a call proves that it came from someone who could.

Who serves the door

The door has two hosts, and one lock decides between them:

  • The Hub. A Hub that runs on its default data folder, or with --door, opens the door when it starts. An agent and a remote never do.
  • The standalone host. When no Hub runs, a tool can start the Hub without its window, hub --head-less --door, if you allowed it. Turn on Keep the Trove door open without the HUB window in the Hub's Trove settings. When that Hub starts later, it asks the standalone host to hand the door over, and the host ends after its running calls.

A Hub that finds another Hub holding the door serves none. It waits up to a minute, then works as a client of the Hub that has it.

What a call can do

A call names a task and its arguments. The door host runs it as one OPAL plan, with the same grants, preconditions and history as a call from the Hub's own chat. A call is refused quickly and by name when it cannot run:

  • An unknown task answers 404. A spec.* task on a door whose spec database is not open fails instead, and names the identity that the door serves: a head-less host with a locked hive, or a node with no identity, has no spec database.
  • A task whose scope you did not grant answers 403 and names the scope. You grant and revoke scopes on the Hub's Door permissions page. Three ways lead there: the Settings tab of Trove, the Door category of the Trove settings, and Permissions in the OPAL group of the sentient lobby.
  • A task that asks before every call answers 409 when nobody can answer: on the standalone host, run that call in the Hub instead.

Calls whose tasks use different resources run at the same time. Calls on one resource run in order, and a call that waits more than 30 seconds for its resource answers 503 and is tried again.

A lane is a composition

A lane is a name, a color and an active plan. Everything else belongs to a part: the lane's worktree to the worktrees part, its session to the sessions part, its builds to kiln, and its work units to the spec database. You can also compose the parts by hand, with no lane at all: a worktree, a session in it, and a build of it.

Recurring specs

Some work never ends. A lint debt or a count of raw owning pointers goes down with each fix, and goes up again with the work of other people. A recurring spec is an ordinary spec with one switch, Recurring. When the switch is on, a schedule of clockwork starts a run at its times. When the switch is off, the schedule pauses, and every setting and the history stay, dormant.

A run uses the parts in turn:

  1. The worktrees part makes a detached worktree at the head of origin/main. Trove measures each probe there: the finding count of a lint check, or the matches of a regular expression. This is the before value.
  2. The specs part copies the template unit of the spec into a new unit, and the run gives it to a lane, as trove.dispatch does.
  3. The sessions part runs the session in the lane's worktree.
  4. Trove measures each probe again, on the head of the lane's branch. This is the after value.
  5. Trove, not the session, records the standard STD-MEASURE and judges the run. A probe passes when it is better than before, or meets its target.

The spec database keeps every sample for good. So the history shows the trend of each probe, and the drift: the change that other work made between two runs. Example: a run lands at 945, and the next run starts at 952. The drift is +7.

Trust

A run leaves its work on its lane's branch, until you trust the spec. Then a run that passed its judgement lands on main by itself. Trust is a choice that you make in the Hub, one spec at a time. A change to the run plan clears it.

The lander is mechanical C++ in the worktrees part. It works in a worktree of its own, and no model takes part. Each step is a guard: the kill switch, the window, a clean rebase, a diff that is not empty and under the delete limit, the verify step, the probes on the exact commit, and a push that is never forced. When main moves, the lander tries again, at most three times in a run. Then it defers the landing to the next run. The door never gets the scope spec.trust, so a session can never trust a spec or land a run.

Run a recurring spec and Trust a recurring spec give the steps.

One writer

All the state of the parts for one identity has exactly one writer: the process that holds the door's lock. Nothing else stops two Hubs from opening one data folder, so the door's lock decides. The spec database keeps its own rule on top of that: one database file for each sentient and device.

The door host also backs the spec database up: once a day, at the first call after midnight, and before it opens a database of an older schema. The door.status task reports when the last backup ran and why it failed, if it did.

In this section
Topics
explanation trove door opal
See also