slices.md takes the rebuild from the reset to one demonstrated
path (slices 0 to 3). These slices take it on to parity with the ocx
branch, whose accepted release people and agents still use, so that release
can be retired, and then past it (the maintainer, 2026-10-06). Each says what
it replaces at the ocx tip
(a46d73f5bf), what
it needs first, and what it decides rather than copies. As before, a slice
is a check-in that implements one function, a typed tool reachable from the
CLI, the CGI and MCP unless it says otherwise, with specs and coverage. The
numbers name the slices. Since protocol v1, parity-v1.md
keeps this list, and this page is the record of how it was first built.
The ocx tip's programs, read for this list on 2026-10-06: task (an agent's
turns), workspace, audit, console, reviewer, the CGI ocx-cgi,
thread, the hook wake and the daemon ocxd, with tools/deploy.cr run by
crystal run. What ocx2 already has in their place: stage, accept and
rollback, and status.
Slice 4: record a verdict
An audited verdict on a check-in (PLAN.md, "Audit by
sample"). Slice 0.5 stripped audit from ocx2
(2b7ea5bea9), so
until this slice is built the ocx release's audit records verdicts.
- Input: the check-in; the verdict,
passorfail; the note. - Who: a login with Fossil's check-in capability (
i), since Fossil drops a tag from a login without it and still reports the sync done; and not the check-in's author, since a verdict is a second login's (PLAN.md, failure demonstrations). - What it does: tags the check-in
auditedwithVERDICT: NOTEas the caller, from the CLI in the caller's clone and then a sync, asocx's does, and from the CGI as slice 2 settles a change as the viewer; then reads the tag back from the server and fails when it was not kept. - Output: the tag's artifact, and the verdict as the server holds it.
- Replaces:
audit [CHECK-IN] pass|fail [NOTE-FILE], which does not refuse a check-in's author; only its review queue ignores one. - Built:
audit CHECK-IN pass|fail NOTE(spec/ocx/verdict_spec.cr); the note is an argument, not a file.
Slice 5: the git export
Not a tool: the program served as git, or git-next from the release
offered as next, answers git's smart HTTP for the mirrors outside OCX that
fetch from it.
- What it does: for
<ext>/git/NAME.git/…, serves the directory that NAME.fossil'slast-git-export-reposetting names, read-only:info/refs?service=git-upload-packandgit-upload-pack, a gzipped request accepted, a body over 50 MB refused, a push refused with 403. - Who: a viewer who may read code (Fossil's
oorh). - Replaces:
ocx-cgi's export (src/ocx/git_http.crat the tip). Git is started in one place, with onlyPATHin its environment (precept I7, Single Process Site). - Built: the entry point
git(spec/ocx/git_export_spec.cr); the maintainer's linksocx2-gitandocx2-git-nexttry it beside theocxrelease'sgituntil the cutover repoints that.
Slice 6: forum records
What slice 2 does on a ticket, on a forum thread, so milestone-sized work and an agent's turns can live on a thread, as this branch's own work does.
- Input: a title and text for a new thread, or the post replied to and the text; optionally a post to read on from.
- Who: a login that may post to the forum (Fossil's
3or4); the post is the caller's, made as slice 2 settles a change. - Output: the post's hash; read on from a post, also what others posted after it, and the next post to read on from.
- Replaces:
task --writeon a thread (with--reply-toand--after) andthread. - Needs first: slice 2.
- Decided: OCX Records are ticket changes or forum posts, and
create --titlemay start a thread with one, since A5 keeps only a run's outcome out of new threads (the maintainer on f1b86b6ac6, c39f5c7969: "i think that's a good start"; c8c9ddddc6: "continue"). - Built:
post POST TEXT [--after POST](spec/ocx/post_spec.cr), from a clone, by push, which needs Check-In; the web page leaves posting to Fossil's forum page.
Slice 7: where work stands
Read-only: what a record says now, for the people and agents working on it, derived from the record alone.
- Input: a ticket or a thread, and a login, the caller's unless named.
- What it does: says the standing (not asked, pending, or answered with its report); what waits on the login (what others posted since its last turn, and the root post until it is answered); the questions put to the viewer and the open questions, derived and never stored (precept C4, Question Shape); and, once slice 8's daemon runs, a thread's agent state as JSON for Stone.
- Replaces:
task --status, whattask --waitwaits for,workspace show, the console's For you and Open questions, and/ext/ocx/status?thread=ROOT. - Needs first: slices 2 and 6. Its name is not
status, which says who and where a run is. - Unreviewed: where work stands is read from the order of a record's turns alone, since what OCX parses is JSON (the structure precept): a report or a question in text is for people to read, so "not asked" and the open questions wait for typed entries, if wanted (the report and note rows go to slice 8, open questions to slice 13); a thread's agent state as JSON comes with slice 8's daemon.
- Built:
standing RECORD [--login LOGIN](spec/ocx/standing_spec.cr).
Slice 8: agents that answer
The runners that turn what waits on a unit into answers on its record.
- Runners: claude and codex, each in one adapter with a conformance spec that runs the real CLI (precept I1, Runner Isolation); a session's prompt, with OCX's conventions in it; a session started at a terminal as well as by the daemon.
- Closing a turn: an answer the agent did not post itself, its printed answer or the file it leaves, posted as its turn, and the tree's changes committed, once verified, with Intent, Expression and Demonstrates lines.
- Only verified work is committed: after the unit's named check passes in a fresh sandbox, by the unit's own login in its own sandbox, never by fossil on the host over files a session controls. A failed check, an interrupted runner or an exhausted budget leaves the changes in the tree for inspection and posts a failure report naming them; at most 200 paths are committed at once.
- The daemon, for sessions that stay (moved here from slice 3): it starts
each unit's process in its own process group, keeps its standard input and
output open, writes each turn to its input, and appends its output to the
unit's events file, which the CLI, CGI and MCP present. It keeps what the
ocxdaemon learned: started from the CGI or the hook, idempotently; no relaunch loop; sessions it did not start are left alone (linux.md). The hook only wakes it, through a pipe opened without blocking. - MCP for a unit:
ocx.contextandocx.report(PLAN.md's bound surface) in place oftask --wait,--writeand--mark; the daemon, not an idle agent, drives the next turn. - Replaces:
workspace start,src/ocx/runners/andsrc/ocx/cli_runner.crat the tip. - Needs first: slices 3 and 7.
- Unreviewed:
- A turn is a tool,
turn, taken from the command line on the served host or by a record the hook works through; it outlasts a web request, so the page records a call. The daemon then gives turns to sessions that stay. - Every fossil act for a unit runs in its sandbox as its own login: the
pull, commit and push that close a turn, its turns posted, its clone
read, and create's pull of an existing clone, since what a clone says
runs (
fossil.md). OCX writes its own files in a workspace through a fresh file renamed into place, and reads only plain ones, never a link a session left. - An agent's login files are its login's own, in
AGENTS/LOGIN, bound into its sandbox; never the host account's, whose agent settings a session could rewrite for the host to run. Its program is the node's, named only on the served host. - Only work from an agent that exited 0 is committed. One that did not finish is reported with how it ended, and its printed error is never posted as its answer.
- The prompt is a document people edit,
docs/prompt.md, compiled in; OCX parses none of it. What OCX says of a turn is a typed report entry,{"ocx": "report", "summary", "files"}, as the unit; the text notations stay what people and agents write. - An OCX entry addressed to a node (a call or a response) is no turn,
so a recorded call to
turndoes not itself wait on the unit. - claude continues its conversation where its own files show one in the
tree, since
--continuefails where there is none. - A session that stays is a
serveprocess per workspace, not an agent kept open: each turn runs the agent afresh, asturndoes, so each turn's limits and verification hold, and claude continues its conversation. There is no daemon process:startdetaches each session undersetsid, and the hook writes its wake pipe directly. A session's files are beside its workspace, out of every sandbox; the reference kept its pipe in the workspace, where a session could make it a link to a file the hook would then write as the server's account. - A turn would outlast a web request and hold up the hook, so the page
and a record start the unit's session instead;
turnis the command line's.
- A turn is a tool,
- Built:
turn RECORD LOGIN RUNNER [--check COMMAND] [--model MODEL] [--program PROGRAM](spec/ocx/turn_spec.cr); the claude and codex adapters (spec/runners/); and sessions,start,serveandstop, the hook waking them andstandingshowing them (spec/ocx/session_spec.cr); and a unit's bound tools,contextandreport, at its command line and over MCP (spec/ocx/bound_spec.cr). Still to come here: a limit on a task's processes, which counts them per host user, so it needs a host user per unit; and the runners' MCP clients pointed atocx2's MCP server, whichocx2on the path stands in for.
Slice 9: supervision
What a setup or admin viewer needs to keep sessions and the daemon running.
- Sessions: the list (running, starting or stopped, and the release each runs), a session's page with the tail of its log, Stop, and a restart of stopped sessions that stay, on the current or the previous release.
- The daemon: its health and the tail of its log, stop and start, and a restart in place when accept or rollback changes the release served.
- Releases: each one linked to its check-in, and next to what changed since current.
- Replaces: the console's Sessions, Workspaces and Daemon pages, its
stop, restart and daemon actions,
task --markand/state. - Needs first: slice 8, whose daemon it supervises. Unreviewed choice, not copied: what may start the daemon; the tip's CGI starts it on every request, an anonymous GET included.
- Unreviewed: slice 8 has no daemon, so nothing starts one: only
startandrestart, which need admin or setup, start a session; supervising is listing the node's units, every workspace, so also the console's Workspaces page, and restarting a stopped session from the restarting program's release. - Built:
unitsandrestart RECORD LOGIN, and each release on the web page linked to its check-in, next to what it changes from current (spec/ocx/session_spec.cr,spec/ocx/styles_spec.cr).
Slice 10: the hook, installed
- What it does: installs or removes
ocx2-hookon a repository of the login group, and says whether it, another hook or none is installed, and whether backoffice-nodelay is on. - Who: setup.
- Replaces: the console's hook page and its hook and unhook actions.
- Needs first: slice 0.5. Slice 3 relies on the hook, so this comes before slice 3 is shown on the served host, where it also shows what is not yet seen there: the backoffice firing the hook for a web post.
- Built:
hookandunhook, and where the hook stands instatus, its last run among it (USAGE.md, "Install or remove the hook").spec/ocx/hook_spec.crshows a scratchfossil server's own backoffice running the installed command for a web post, once a page answers 200 (fossil.md, "Hooks").
Slice 11: listening, and CI
- Listening: a unit listens to another record or to a branch, and stops, by a note on the record listened to, which its session reads (slice 3, "One record for workspace, session and listeners").
- CI: a mechanical session on a listened branch runs the checks on each
new check-in, tags it
ciwithgreenorredand the last line, and notes a red one on the record. - Replaces: the console's listen and unlisten actions, and the tip's
command sessions (
src/ocx/command_runner.cr). - Needs first: slice 3. Unreviewed, not copied: who may start CI; at the tip any check-in on a listened branch does.
- Unreviewed: CI is a unit bound to the branch it tests, not a listener:
its binding's branch is that branch, and it tests the branch's newest
check-in once, when it has no
citag yet, in its sandbox, tagging it as the unit. Only admin or setup start CI, byciat a terminal or a session whose runner isci; any login's check-ins are tested. A red one is a report entry on the unit's record, since OCX writes no text notation. - Built:
ci RECORD LOGIN CHECK [--branch NAME]and thecirunner for sessions (spec/ocx/ci_spec.cr);listen RECORD [--stop]from a unit's tree, answered byturnand its session (spec/ocx/listen_spec.cr).
Slice 12: jobs at a ref
- What it does:
Run: LOGIN at REFon a job's record runs that login's job at REF and answers with its result, the tail of its log fenced, and its report files, read safely against pipes and links. - Replaces: the console's job page and its run-job action
(
src/ocx/job.cr). - Needs first: slice 11. Unreviewed, not copied: who may start a job; at the tip anyone who can post on the job's record can.
- Unreviewed: a request is a typed entry on the ticket, run only for admin
or setup, as the check runs the code at REF, else answered not run; reports
are read in the sandbox. Built:
request,job(spec/ocx/job_spec.cr).
Slice 13: activity and the review queue
- What it does: lists the work in progress, the check-ins on agent
branches, the posts in threads and the audits; and the review queue:
check-ins that change files with no
auditedverdict by a login other than their author, and the newest entry waiting on each record a login took part in. With slices 7 and 9 it is the console's every section. - Replaces: the console's Work, Check-ins, Posts and Audits views, the
consoleprogram andreviewer. Not copied:reviewer --wait, a timer; the hook wakes a reviewer as it wakes any unit. - Needs first: slices 4 and 7.
- Unreviewed: the views read the served repository or a clone; a verdict counts when Fossil received it from another login than the check-in (a clone's cards are said unverified); open questions are not listed (slice 7).
- Built:
queue [--login LOGIN]andactivity(spec/ocx/views_spec.cr).
Slice 14: closing a unit
- Terminate: refused while a process runs in the workspace or its clone holds what the repository lacks; otherwise a note on the record, and the workspace removed.
- Collect: the same for every workspace whose ticket is closed or whose thread has been quiet longer than a given number of days.
- Replaces: the console's terminate action and
workspace gc. - Needs first: slices 1 and 3.
- Unreviewed: the clone is pushed as the unit before what it holds is
counted; uncommitted edits keep a unit too; a ticket is closed only at
Closed; the note is a report entry by the unit. - Built:
terminate RECORD LOGINandcollect [--days N](spec/ocx/close_spec.cr).
Slice 15: units made from the page
- Templates: the wiki pages
workspace/NAMEandsession/NAMEas the definitions a unit starts from. - The form: a setup or admin viewer makes a unit from a template, previews its definition without writing anything, and starts a thread for it when no record is named.
- Replaces: the console's add-workspace form, its preview and launch.
- Needs first: slices 1, 3 and 6.
- Unreviewed: one template,
session/NAME, holdsstart's options; the preview islaunch's dry run; a record is named, as A5 starts a thread only incgi.cr,launch.crormaintainer/, and I7 keeps Fossil's formats infossil/. Built:launch(spec/ocx/launch_spec.cr).
Slice 16: a local model as a runner
The native runner for Gemma (PLAN.md, phase 2 and "Visible model exchanges"): every exact request, advertised tool schema, response and tool result posted to the prompting record before the next step, within a fixed budget of steps and bytes.
- Replaces:
src/ocx/native_runner.crat the tip. - Needs first: slice 8.
Slice 17: a post nobody heard
When a post arrives for a unit whose session is not listening, a note on the record says so, unless its author is an agent.
- Replaces:
src/ocx/unheard.crat the tip. - Needs first: slices 3 and 8.
- Built: in the hook, as the node's login,
{"ocx":"unheard"}on the ticket or thread, which is no turn (spec/ocx/unheard_spec.cr).
Milestone: the ocx release retired
The cutover. With slices 1 to 10, agents answer and record verdicts through
ocx2, mirrors fetch from its export, the hook and daemon are its own, and
AGENTS.md can send agents to it; then the ocx release
can stop serving. It waited too on the git round trip the maintainer asked
for (slices-git.md). Retiring it is the maintainer's,
with these lists in hand, kept current as slices land; its links are made in
scripts/start-fossil (HISTORY.md 22).
- Supported after slices 1 to 10: creating a unit's workspace (1); OCX Records and responses on tickets (2), and records that run a task (3); verdicts (4); the git export (5); turns on forum threads (6); where work stands and what waits on a login (7); agents' turns, sessions that stay and verified commits (8); units and their sessions supervised (9); the hook installed (10). Landed: all ten but slice 8's process limit, which needs a host user per unit; of the rest, CI and listening (11), jobs at a ref (12), the views (13), ending units (14), units from templates (15), the note for a post nobody heard (17), the export kept current (40) and importing a git repository (39): the git round trip is shown.
- Still the
ocxrelease's, or not yet anyone's: a thread started for a unit (15); a local model (16); refresh and onboarding (39, 37).
Not copied
- The outbox and clones of a repository file: clones are HTTPS only, and a unit's password is set when its workspace is made (HISTORY.md decision 29).
- Password files, and provisioning logins from the console (decision 29).
- The one-shot runner,
task --cliand--provider, which sessions replace. - The release root's token (decision 30), and
deploy --installand--served: the first accept is trusted on first use (decision 31), andstart-fossilmakes the served links. - The bare
-pageHTML and the clock in the viewer's zone: the page is Markdown in Fossil's skin (decision 33). - Running unconfined when
bwrapis missing, asOCX run:and the native runner do at the tip: slice 3's sandbox refuses instead. - The hook opening the served repository inside Fossil's write transaction (precept I5, Rollback Journal): it hands the hashes on.
- Read-only peer clones, until PLAN.md's "Project context" row is taken up.
Past parity
PLAN.md's gap table holds what OCX does past ocx: a workspace-bound MCP
surface, distributed nodes, grounded search and the rest. One follows here
because the daemon brings it.
Tools planned past parity
As USAGE.md described them, moved here whole: PLAN.md's bound surface.
- Read the record or the code: Returns a bounded excerpt: posts, a ticket, a file or a line range, or a diff. It is taken from the node's clone, never from the served repository's database, and never includes a credential.
- Edit scratch: Applies a validated patch to a unit's scratch tree, as the unit's own login or a person allowed to act for it. Nothing reaches the repository until it is proposed and published.
- Run a check: Runs a named, allowlisted check, such as
crystal run ci.cr, with bounded output and metered CPU and memory. The result goes to the caller, or, for CI, onto the check-in as acitag under the CI login. - Hand off a subtask: Gives a bounded subtask to a local model under its own provisioned login. It offers only the tools that model's grant allows and returns its result. The whole exchange is recorded as JSON on the prompting record. The delegating login's grant must allow the model's login.
- Propose a change: Commits a change to the unit's work branch as the unit's own login, syncs it, and names the branch it is meant to advance. Proposing never merges and never attaches a verdict; integration into the target is a separate, attributed acceptance.
Slice 18: a live feed
Tasks that stay (slice 3, "Short tasks and long ones") need the daemon, the
only source of a live feed, since Fossil holds an ext page's output until it
is complete: server-sent events from the daemon's own port, opened with a
token the CGI mints for one unit (USAGE.md, "Watch a running
unit"). A task that completes needs no feed; its response is its result.