Expand description
Core logic for Voro: the SQLite store, the task state machine, and the
scheduler/scoring. Pure of terminal I/O; every interface (TUI, CLI verbs)
is a thin consumer of this crate. Concepts and invariants are specified in
docs/DESIGN.md.
Re-exports§
pub use scheduler::ActionRow;pub use scheduler::AttentionCosts;pub use scheduler::Candidate;pub use scheduler::DigestRow;pub use scheduler::EffectiveScore;pub use scheduler::Queue;pub use scheduler::QueueRow;pub use scheduler::ScoreBreakdown;pub use scheduler::StateCounts;pub use scheduler::WipGate;
Modules§
- config_
edit - Comment-preserving edits to the user’s
voro.toml(DESIGN.md §5). Wherecrate::agent::AgentsConfigreads the file, this writes it: the single helper the TUI Config screen and thevoro viewerCLI verbs both route through, so the two never diverge on formatting or validation. - scheduler
- The scheduler (DESIGN.md §7): pure scoring and the ordering of the two
views. The store supplies candidates (with
age_daysalready computed); everything here is deterministic arithmetic on those rows. - seed
- The dev store’s fixture (DESIGN.md §5).
Structs§
- Account
Cap - What an agent’s
capverb says about the account it dispatches on: the instant its usage window reopens (DESIGN.md §8). - Agent
Session Entry - One session from an agent’s
sessionscommand output: a JSON array of objects, of which the fields below are read and everything else ignored.sessionId(falling back toid) is the durable reference substituted into{session};cwdandstartedAt(ms epoch) identify a fresh dispatch’s session among its siblings;stateandpidtogether say whether the session is still going (AgentSessionEntry::liveness). - Agent
Template - A named set of verb templates from
voro.toml.dispatch(or its aliascmd) is required and always containsPROMPT_FILE_PLACEHOLDER; it may also carry the optionalSESSION_NAME_PLACEHOLDERandTASK_ID_PLACEHOLDER. The rest are optional, with their{session}/{prompt_file}placeholders validated at parse time. - Agents
Config - The effective agent config: the built-in agents with any
voro.tomlmerged on top, plus the user’sdefault_agentand viewers. Each agent carries itsProvenancesoagent listcan show where it came from. - CapReading
- What a session’s output says about a usage cap. Held in memory only: it is a reading of the current output tail, retaken on the next pass, so it clears itself once the operator continues the session and new output displaces the cap message (§8). Nothing about it reaches the database.
- CapWindow
- When a capped session’s window reopens and whether it has: the one answer the badge and the nudge sweep both read, resolved from the two sources that can give it (DESIGN.md §8).
- Completion
Report - What a reviewer reads a task against (DESIGN.md §8): the completion summary the current cycle came back with, and — on a task that has been sent back — the rejection feedback that summary answers.
- Dep
- DepRef
- A dependency edge resolved for display: the task at the other end of the
edge with its current title and state, plus the edge’s kind. Which end is
“other” depends on the query — the dependency for
Store::deps_by_task, the dependant forStore::dependents_by_task. - Doc
- A plan or design document a project’s work derives from (DESIGN.md §3), and the thing tasks link to so “which tasks came from this plan?” is a query rather than a grep over task bodies. Owned by one project — which is where a relative location resolves — but linkable from a task in any project, since one plan routinely spawns work across several.
- Event
- Github
Issue - One issue from
gh issue list --json number,title,body,url. Those four fields are all gh documents for this command; anything else it emits is ignored. - Launch
Spec - Everything a verb template needs bound to become a command line: which
launch this is, the prompt file written for it, and whether the task earns
the deeper model. Assembled by the caller that wrote the prompt, rendered by
ResolvedAgent::launch_commandorResolvedAgent::plan_launch_command. - NewTask
- Initial state for a task created by a human.
proposedis quick capture;parked/readymean the creator has already triaged their own task. - PrPlan
- Everything the forge needs to open a PR for a review task (DESIGN.md §8):
the branch to push and the title and body of the pull request. Assembled by
plan_pronce the task is proven PR-ready. - PrRef
- A parsed reference to a GitHub pull request. The base repo is recorded
explicitly (
owner/repo/host) rather than inferred from a checkout’sorigin, so a PR opened from a fork is still addressed against the repo where the diff and its review comments live (DESIGN.md §11c). - PrRevisions
- A tracked PR’s revisions, read from
gh pr view --json headRefOid,commits: the current head, and the commits the PR contains. The latter is what answers “is the revision I reviewed still on this branch?” — a rework that appends commits keeps it, and a force-push or rebase drops it. - Project
- Rendered
Message - A
messagetemplate rendered into a runnable command line, plus the reference the session will answer to afterwards where the agent forks (NEW_SESSION_PLACEHOLDER). The caller records that reference only once the send is under way, so a command that never ran leaves the session pointing where it did. - Repo
- A checkout a project’s work runs in (DESIGN.md §3): the execution target
dispatch,
pr/open, worktree cleanup, andimportresolve against. A project owns at least one, exactly one of which is its default. - Resolved
Agent - The agent a task will be dispatched with: the task’s own override if it has one, otherwise the config’s global default, with every verb template resolved.
- Running
Row - A row of the cockpit’s running strip (DESIGN.md §9): one per
running,refining, orwaitingtask, joined with its open session if it has one. A task with no open session (started by hand) still shows, withsession_id/agentNone.started_atis whatelapsed_secscounts from — the session for work under way, the hand-off for awaitingtask — andelapsed_secsis computed in SQL against the database’s clock, so the TUI only has to format it.pr_urlcarries the strip’s PR marker. - Session
- Store
- Owns the SQLite database. All writes go through this type; task state in
particular is only ever changed by the transition API in
transition.rs. - Task
- Task
Edit - Content edits. State is deliberately absent — use
Store::apply. - Viewer
Template - A viewer command template from
voro.toml(DESIGN.md §11a): a shell command run in a task’s checkout — or its worktree — to open its diff. Defined as a named[viewers.<name>]table or the anonymous[viewer]default. The placeholders{path}(checkout/worktree dir),{branch}(the task’s branch), and{base}(the checkout’s default branch) are all optional, so nothing is validated at parse time.
Enums§
- Action
- DepKind
- Error
- Launch
- What a launch is (DESIGN.md §8): the one place a backgrounded or
foreground agent session’s identity is composed. A launch names its session,
its prompt and log files, and its line in the launch log from this single
value, so a new flavour of launch cannot inherit one of those and forget
another — which is exactly how a refine came to be named
voro-{task_id}, literally, on every task at once. - Liveness
Source - Which source of liveness is authoritative for a session (DESIGN.md §8), recorded by the code that spawned the process because only it knows what it spawned. The two differ in one respect: whether the pid the session row holds is the work itself or a launcher that spawned it and exited.
- Mergeability
- GitHub’s mergeability verdict for a tracked PR (
gh pr view --json mergeable, DESIGN.md §8): whether a review task’s branch still merges cleanly with its base. Read fresh and never stored — the same rendered-not-stored shape as the incomplete-report flag — it is what turns aCONFLICTINGPR into the informational[branch conflicts]marker. - Next
Action - The verb a task’s queue row asks of the human (DESIGN.md §3), derived from state × fields rather than stored.
- Priority
- Provenance
- Where an effective agent came from once the built-ins and
voro.tomlare layered, surfaced byvoro agent listso it is clear which half of the config owns each agent. - Refine
Outcome - How a refine round ended (DESIGN.md §6). It rides the
refining → proposedtransition, is logged as the detail of arefineevent, and picks the outcome the round’s session closes with — so the markers on the returned proposal are derived from the round that just concluded rather than from the whole history of the task. - Review
Diff - How much of a task’s work to put in front of the operator.
- Session
Liveness - What a listing entry says about its session, as far as pure logic can tell
(DESIGN.md §8).
AgentSessionEntry::livenessclassifies; thevorocrate resolvesSessionLiveness::WhileProcessLiveswith the process check, sovoro-corestill never touches a process. - Session
Outcome - Task
State - Triage
- Where a
proposedtask goes at triage.
Constants§
- BUILTIN_
VIEWER_ NAMES - The built-in viewers by name, in the order they are probed against PATH when nothing user-configured resolves: the first one installed wins (DESIGN.md §11a). Public because the messages that say what was looked for are written where the failure is surfaced, and none of them should spell the list again.
- CAP_
SIGNATURES - Phrases that mean “held at a usage cap”, checked case-insensitively.
- NEW_
SESSION_ PLACEHOLDER - The fresh-reference substitution in the
messagetemplate, bound to a v4 UUID Voro generates for the send (DESIGN.md §8). An agent whose sessions are held by a supervisor cannot be resumed headlessly while that supervisor lives; it can be forked, which continues the same conversation under a reference the caller names up front. Amessagetemplate carrying this placeholder is declaring that shape, and the session row follows the fork: what Voro binds here becomes the session’s reference. Optional — a template without it resumes in place and keeps the reference it had. - PROMPT_
FILE_ PLACEHOLDER - The prompt-file substitution in the
dispatch,planandmessagetemplates. The working directory is handled by the spawner, not the template. - REVIEWED_
EVENT - The event kind recording the branch revision the operator reviewed. The
eventstable carries it, so nothing about delta re-review needs a column. - SESSION_
NAME_ PLACEHOLDER - The session-name substitution in the
dispatchandplantemplates: the name Voro composes for the session a launch opens (Launch::session_name), so every backgrounded session is findable by a name Voro chose. Optional, and refused on the session verbs for the same reason [MODEL_PLACEHOLDER] is — they act on a session that already exists and has its name. - SESSION_
PLACEHOLDER - The session-reference substitution in the
attach,resume,message,logsandstoptemplates: the agent-opaque reference captured at dispatch (a Claude session UUID, a Codex session id, a tmux session name). - TASK_
ID_ PLACEHOLDER - The task-id substitution in the
dispatchtemplate, the numeric id of the task. Optional — a template that omits it dispatches unchanged — so a template can put the id somewhere other than the session name. Refused onplan, which serves targets that have no task id to bind. - VIEWER_
BASE_ PLACEHOLDER - The substitution in a viewer command template for the checkout’s default branch — the base a task branch is diffed against (DESIGN.md §8).
- VIEWER_
BRANCH_ PLACEHOLDER - The substitution in a viewer command template for the task’s git branch, or
empty when the task has none. Paired with
VIEWER_BASE_PLACEHOLDERit lets a viewer express a diff range ({base}...{branch}) rather than a bare directory (DESIGN.md §8). - VIEWER_
PATH_ PLACEHOLDER - The substitution in a viewer command template (DESIGN.md §11a): the checkout
path of the task’s project — or the task’s worktree, when it has a branch
checked out in one (DESIGN.md §8). Optional — a viewer that acts on the
current directory (
git difftool -d) needs no placeholder.
Functions§
- already_
imported - Whether
body(an existing task’s body) already carries this issue’s URL — the idempotency check that lets import be run repeatedly without creating duplicate tasks. - completion_
report - Read a task’s current completion report off its event log.
Nonewhen the cycle in hand has reported nothing: a task that never completed, and a rework still in flight, whose newest summary belongs to the round that was rejected and so answers neither the feedback nor the operator’s question of what changed this time. - format_
review_ feedback - Build a reject-with-feedback body from a PR’s reviews and inline comments (DESIGN.md §11c), so a GitHub review reaches the agent without retyping. Reviews with an empty body are skipped; the inline comments carry their own text. Returns an empty string when there is nothing to relay.
- is_
builtin_ viewer - Whether a name is a built-in viewer. The write surfaces ask, so removing or editing one is refused as “built in, override it” rather than reported as a viewer that isn’t there.
- issue_
new_ task - An issue mapped to a task, always landing in
proposed: imports are untriaged like any other machine-generated task, and priority is not guessed from labels in v1 — triage assigns it.repo_idcarries the repo the issues were fetched from, so an imported task dispatches into the checkout it came from rather than the project default. - issue_
task_ body - The task body for an imported issue: the URL and issue number stamped at
the top (both for human reference and as the idempotency marker checked
by
already_imported), followed by the issue body verbatim. - location_
is_ url - Whether a doc location is a URL rather than a path. Deliberately a narrow
scheme test, so a bare
docs/plan.mdnever has to be escaped to read as a path. - model_
for_ depth - Bind a session verb’s one placeholder: the reference Voro captured at
launch, shell-quoted so a reference carrying shell metacharacters reaches
the agent as itself. Serves
logs, whose whole contract is a session in and that session’s recent output out. Which model a launch at a given depth runs with (DESIGN.md §8): the deeper one for a deep task where the agent names one, the workhorse otherwise. The one place that rule lives, because two callers now depend on agreeing about it — the launch itself, and thecapreading that has to ask about the window that model is metered against. - parse_
mergeable - Read GitHub’s mergeability verdict out of
gh pr view --json mergeableoutput ({"mergeable":"CONFLICTING"}). Only the two definite verdicts map to themselves; anything else —UNKNOWN, a missing field, malformed JSON, or the empty string a missing or unauthenticatedghleaves behind — degrades toMergeability::Unknown, so no signal is ever mistaken for a conflict. Pure of I/O; theghcall lives in thevorocrate. - parse_
pr_ revisions - Read a PR’s head and commit list out of
gh pr view --json headRefOid,commitsoutput. Malformed or missing fields degrade to empty — no head and no commits — whichplan_review_diffturns into the full diff, so an unreachableghnever blocks a review. - parse_
reset_ epoch - Read an agent’s
capverb output as the instant its window reopens, orNonewhen it said nothing (DESIGN.md §8). - parse_
sessions_ json - Parse a
sessionscommand’s stdout. Entries without any id are skipped rather than failing the whole listing; anything that is not a JSON array is an error, so a misconfiguredsessionsverb surfaces rather than reading as “no sessions”. - plan_pr
- Validate that a task can have a PR opened from its done-time state, and if so
assemble the
PrPlan(DESIGN.md §8): areviewtask carrying both a branch (the work to push) and a completion summary (the PR body; the caller supplies the latest). Each gap fails naming what is missing — state, branch, or summary. The branch gap is the one no advertised verb leads to: a review task without one asks for accept rather than pr (DESIGN.md §6), so this refusal is reached only by an operator namingpron it directly. Pure of I/O. - plan_
review_ diff - Decide what a review should show (DESIGN.md §8).
last_reviewedis the revision recorded when the operator rejected,headthe branch’s current tip, andstill_on_branchwhether that recorded revision is still reachable from the head — false after a force-push or a rebase rewrote it away. - projects_
for_ new_ task - The projects a new task can be created in, in the order to offer them
(DESIGN.md §9). Archived projects are dropped —
Store::create_taskrefuses them (§5), so offering one is offering a choice that can only fail, and in the$EDITORand planning flows it fails only after the operator has written the task out. The rest sort by weight descending, which is the one per-project priority Voro holds (§7), with name ascending inside a weight so the order is stable. Weight 0 is a snooze rather than a retirement, so a parked project stays offered and sorts last. - read_
cap - Read a session’s output tail as a cap reading, or
Nonewhen nothing in it says the session is capped. - render
- Fill
templatefrombindingsin a single left-to-right pass: each bound placeholder’s value is emitted verbatim and never re-scanned, so a value containing another placeholder survives whatever order the bindings are given in. An unrecognised{…}is copied through untouched, which is what makes composing nested blocks safe — render the inner block first, then bind the finished text. - render_
cap - A
captemplate rendered into a runnable command line (DESIGN.md §8). The model is bound exactly as a launch binds it — pasted in as the opaque name the operator configured, Voro being model-blind — and a template naming no model renders unchanged, which is what makes the per-model question optional rather than required. - render_
message - Bind a
messagetemplate’s placeholders in one pass, so no value’s own braces are re-scanned: the session reference Voro captured at dispatch, the file holding the message, and — for a template that forks — a freshly generated v4 UUID for the session the send opens. All are shell-quoted; the references are agent-opaque text, not tokens Voro may assume are bare. - render_
session - shell_
quote - Single-quote a path for safe substitution into an
sh -ccommand line. - strip_
ansi - Drop terminal escape sequences, keeping the spacing the surviving text had on screen.
- was_
rejected - Whether a task has been reviewed and sent back at some point — what makes a redispatch a rework rather than a first attempt (DESIGN.md §8).