What OCX is for, the precepts that guard it, what is still missing, and the order of the work. README.md holds the axioms and virtues; knowledge-map.json says which document holds each other topic. When this plan and the documents it points to disagree, they govern and this plan is corrected.
What it is for
OCX gets coding work done by people and agents together, with every step on a Fossil record that anyone with access can read later.
- A task has one hash: a ticket or a forum thread. Its specification, questions, progress, evidence and result stay together on that record.
- Any agent can take the task: a person in the browser, a hosted agent such as Claude or Codex, or a local model such as Gemma, whose lower reasoning OCX tolerates by bounding what each step asks of it (the maintainer, 834ceded37: "collaborate with agents in ways that makes them efficient and tolerates lower reasoning"). Each works to the same task and report contract, and each result names the user that produced it, so agents can be compared on the same saved tasks.
- Each change states its intent, how it is expressed and what demonstrates it. CI and independent reviewers attach their verdicts to that check-in.
- Acceptance stays with a person: merging and serving a release are explicit, attributed actions, and a release can be rolled back.
Precepts
Each precept is a testable consequence of a README axiom and virtue. The
existing IDs remain stable for their guards: C derives from Clarity
(README axioms 2 and 3), I from Loose Coupling (axioms 1 and 5), and
A from Demonstrability (axioms 1 and 4). The latter two prefixes retain
the older names Interchangeability and Accountability; they do not introduce
extra axioms or virtues. Parsimony (axioms 1 and 4) also shapes precepts C1
(File Boundedness), C7 (Pinned Interfaces), and I7 (Single Process Site): each
bounds a different source of needless complexity. A precept without a guard
spec is a memory, not a mechanism. The ledger spec fails when a precept has no
spec tagged # precept: <id>.
The cooperative premise in Axiom 3 is not a security assumption. Axioms 4 and 5 account for fallibility and the consequences of integration, so the derived controls remain necessary: precept I4 (Server-Only Writer) limits access to the served repository, precept I6 (Pluggable Confinement) specifies a replaceable confinement mechanism, and precept A2 (Artifact Audit) records review verdicts.
Conflict check, done before admission:
- Precept C2 (Single Owner) and precept I4 (Server-Only Writer) agree: the repository owns durable facts, while ephemeral facts stay outside it.
- Precept I1 (Runner Isolation) and precept I4 (Server-Only Writer) agree: a runner's clone is its own.
- Precept A4 (Staged Deployment) and precept I4 (Server-Only Writer) agree: deployment does not write a repository.
- Precept A2 (Artifact Audit) and precept C2 (Single Owner) agree: an audit is a tag on the check-in it judges, not a config row.
No precept requires an agent to open a served repository, so precept I4 (Server-Only Writer) has no exception.
| Id | Name | README virtue | If … then … | Guard |
|---|---|---|---|---|
| C1 | File Boundedness | Clarity, Parsimony | If a part is to be read whole, then no source, spec or Markdown file exceeds 400 lines, and every document renders with its links leading somewhere. | spec/guards/size_spec.cr, spec/guards/documents_spec.cr |
| C2 | Single Owner | Clarity | If a fact is to have one owner, then no code writes runtime or ephemeral state into any repository's config table. | spec/guards/config_state_spec.cr |
| C3 | Stated Change | Clarity | If a change is to be stated, then its check-in comment carries Intent, Expression, and Demonstrates lines. | spec/guards/checkin_spec.cr |
| C4 | Question Shape | Clarity | If a question is put to a person, then OCX frames it as a question message (its user, the question, and optional options, stakes and references), and a person's answer as a decision; the notation is never typed by an agent or a person. |
spec/guards/question_spec.cr |
| C5 | Canonical Naming | Clarity | If the project is named in code, then the name is OCX; the origin names appear only under a History heading. | spec/guards/naming_spec.cr |
| C6 | Explicit Arguments | Clarity | If configuration is to be stated, then it is an explicit argument; no code, guard, or CI step reads an environment variable, except that the program's wrapper takes from it by value the variables Fossil describes a CGI request with (the repository, user, capabilities, nonce and base path; the method, query, sub-path, body length, HTTPS flag, host and Referer) the build settings that hold no secret, and the terminal's type (TERM), which a run at a terminal passes on (the maintainer, 7242762209), and of the rest only their names. |
spec/guards/environment_spec.cr |
| C7 | Pinned Interfaces | Clarity, Parsimony | If an interface is to be relied on, then it is listed in docs/interfaces.md with the spec that pins it, or the rebuild slice it is pending for, and every notation head the code writes is listed there. | spec/guards/interfaces_spec.cr |
| I1 | Runner Isolation | Loose Coupling | If a model or an agent's program is to be replaceable, then its invocation and output formats live only in its adapter, and the adapter has a conformance spec that runs the real CLI. | spec/guards/runner_adapter_spec.cr |
| I2 | Repository Portability | Loose Coupling | If a repository is to be replaceable, then no source names a specific repository or host path; the repository is always a parameter. | spec/guards/repository_neutral_spec.cr |
| I3 | Pinned Toolchain | Loose Coupling | If the toolchain is to be replaceable, then CI prints and pins the dependency ledger, compiler included; a developer's run on another compiler is reported as not a gate result, and the merge gate refuses any compiler but the pin. | spec/guards/dependency_ledger_spec.cr, spec/gate/compiler_gate_spec.cr |
| I4 | Server-Only Writer | Loose Coupling | If Fossil is the store, then only the Fossil server, and the programs it spawns to answer a request, open a served repository; every agent works in its own clone under its own login and syncs. | spec/host/served_writers_spec.cr |
| I5 | Rollback Journal | Loose Coupling | If a served repository is to stay compatible with remote clients, then it runs in rollback-journal mode, never WAL. | spec/host/journal_mode_spec.cr |
| I6 | Pluggable Confinement | Loose Coupling | If a session is to be confined, then the confinement is a written plan and one replaceable call site: bwrap is named in one source file and started in one place, so another mechanism can take the same plan. |
spec/guards/confinement_spec.cr |
| I7 | Single Process Site | Loose Coupling, Parsimony | If an external program is to be replaceable, then src/ starts it in exactly one place: one Process call per program, inside the function that wraps it, which is where another implementation takes over; callers reach it only through operations named for what they do, its transport private and its command words and SQL in its module. The maintainer's standing rule, stated 2026-09-23 after fossil was started from four places and only one of them had been kept from the console's environment, and 2026-10-07 after Fossil.run passed fossil's words through. |
spec/guards/external_programs_spec.cr |
| A1 | Visible Evidence | Demonstrability | If a change is to be shown, then the demonstration its check-in names exists in the tree. | spec/guards/checkin_spec.cr |
| A2 | Artifact Audit | Demonstrability | If a change is to be trusted, then its audit is a Fossil tag named audited on the check-in itself, whose author is the login that added it and whose value begins with the verdict pass or fail; the suite prints coverage and verdicts. |
spec/guards/audit_spec.cr |
| A3 | Parity Gate | Demonstrability | If a merge is proposed, then the precept ledger has zero gaps and every row of its chosen parity contract cites a demonstrated check-in. | spec/guards/ledger_spec.cr, spec/guards/parity_spec.cr, spec/gate/parity_gate_spec.cr |
| A4 | Staged Deployment | Demonstrability | If a build is to be shown before it is served, then serving is a separate, named step: OCX's served link resolves into a release, never into a checkout. | spec/host/deploy_spec.cr |
| A5 | Origin Home | Demonstrability | If a run is to be shown, then its outcome is written to the artifact that prompted it, never to a new ticket or thread of its own. | spec/guards/outcome_home_spec.cr |
Host guards for precept I4 (Server-Only Writer), precept I5 (Rollback
Journal), and precept A4 (Staged Deployment) live under spec/host/, tagged
host, and run with crystal run ci.cr -- host; a bare crystal spec runs
them too, and tells the truth about the host it runs on. They take nothing from configuration: the served
directory and the served CGI root are read from the running Fossil server's own
command line (--repolist, --extroot), and when no server runs here they are
pending with that reason, never silently green. On 2026-09-21 they failed on
the live host: three served repositories were in WAL mode, migrated in place
the next day, and the served CGI links resolved into a checkout. Precept A4
(Staged Deployment) judges OCX's own link; trunk's stand until the maintainer
takes them down (HISTORY.md decision 17).
Where it stands
Protocol v1's definition is stable: a person or program asks a node to run a process, talks with it, learns how it ended and ends it, all on the record, on agent machines. The node builds all of it, a run on a terminal since HISTORY.md decision 82. What trunk did that ocx2 still lacks is docs/parity-v1.md; what OCX is meant to do past it, and where each stands:
| Function | State | What is missing, and what shows it done |
|---|---|---|
| Shared records | built | Runs, stops, reports, deliveries and kept logs on one thread or ticket (protocol v1, section 3). |
| Confined execution | built | Every run in a sandbox it states, with wall, cpu, processes and files limits. Memory needs a cgroup: until then a node refuses it. |
| Event-driven work | built | One daemon per machine waits on Fossil's chat, pulls whole clones and reconsiders unsettled runs; each watcher handles reports, deliveries and stops (How a post reaches an agent). |
| Distributed work | built | ocx2 daemon NODES on an agent machine's clones, as a node user whoever has that machine's command line registers for and an admin may approve with one press (HISTORY.md decisions 73 and 76); a build there takes its check-in's files and holds no credential, and its node sends its verdict and the files it shares (decisions 70 to 72). Still to show live: a build machine or lab board running a build and its verdict and files reaching the server. |
| Hosted agents | pattern | A pattern per agent, such as run/claude, tried on a thread: a turn per post with deliveries: start, or one long session on a terminal (terminal), which a person at its node's host joins with attach, both built (decisions 82 and 83). |
| Local models: the native agent | built | ocx2 --mcp-ollama, OCX's own program for a local model, named as a run's command, below; it holds the conversation the battery (battery/main.cr) measures, in which qwen2.5-coder:7b passed 28 of 73 trials over four runs with the checkout tools as built (run 4). Still to show: the pattern run/gemma on the server and its first proof. |
| Visible model exchanges | built | The native agent prints each reply as a line of JSON before any call it asks for runs, and each tool's answer as a line after it, the first request sent and every reply received exactly, within what its run keeps of its standard output, kept always, which the node posts where the run is when the process ends; the battery keeps the same in its tech-notes. Watching an exchange live is the live status the maintainer described over SSE (KEEP.md, "Seeing what runs, and joining in"), never a post. |
| An agent's MCP surface | built | The checkout tools below, for an agent's own work in its run (decisions 65 to 68), measured by the battery. Not shown: that a weak model does as well when MCP offers every tool its user may call, as a run's MCP does, and not only these. |
| Agents that cannot hold a key | built | run/mcp-tunnel, a bridge to OpenAI's Secure MCP Tunnel, so such an agent's contributions are saved with no inbound port opened (the maintainer, 2026-10-14; decisions 58 to 60, docs/remote-agents.md). Shown: a ChatGPT workspace listing the tools through it, and runs of it on the record. Still to show: an agent's check-in landing through it. Anthropic's MCP tunnels are not tried. |
| Comparable agents | missing | One saved task run by a person, a hosted agent and the native agent, their edits, checks and reports compared, failures included. |
| Reviewable changes | partly | audited verdicts are built, and a one-shot build's ci verdict, which its node writes (decision 71). A check's session sending a build of each check-in it is given is a pattern, run/ci, written for an admin to save and not yet tried live, and a ci verdict counts only from the build's node (decisions 87 and 88). Missing: a local model's cited review report beside a distinct user's verdict; the battery's audit trials found no local model yet that tells a faulty change from its clean twin reliably (tech-note 952120c490). |
| Branch contributions | gap | An agent works on its own branch and names the branch it aims to advance; acceptance is a person's attributed act. Fossil grants check-in to a user, not a branch, so a wrong-branch check-in is reported, not prevented. |
| Consistent tools | built | Each tool one typed definition across the command line, the CGI page and MCP (HISTORY.md decisions 32 and 33). |
| Reversible releases | built | stage, accept, rollback; accepted from the served page on 2026-10-06. Still to show: a rollback there. |
| Grounded search | evaluate | Trunk has src/vec_search.cr and an index; restore only with a scenario that needs it, its vectors kept outside any served repository. |
| Documentation freshness, model improvement, project context | evaluate | Trunk has candidates; each returns only with evidence of benefit. |
Agents on protocol v1
How each kind of agent works through runs. What is marked to settle is a design for the maintainer to decide before it is built.
Hosted agents. How Claude or Codex runs is a pattern's data, never OCX's
code (HISTORY.md decision 40): its program, arguments, sign-in
and environment in a run's layers. It answers with ocx2 post and checks in
from its clone as its run's user.
The native agent for local models (built on branch agent-tools,
HISTORY.md decision 78). OCX's own program, named as a run's
command, so the protocol stays agent-free: ocx2 --mcp-ollama URL --model
NAME --steps N --system TEXT. It reads its run's line and a delivery's on
its standard input, works in its run's checkout through the checkout's group
of tools below, every one but ocx_post and ocx_thread, as MCP serves them
to its run's user, refusing a call to any other, and talks to the model NAME
at the Ollama server URL; the model, its words and its budget are the run's
command's arguments, its byte budget the run's own process.keep.stdout,
and its clock the run's wall. It takes a run that keeps its standard output
always, and a session only with deliveries: start. Each reply is a line
of JSON on its standard output, printed before any call it asks for runs,
and each answer a line after it, the first request and every reply exactly;
no request larger than the run keeps is sent, no line past it printed, and
no call run without room for its answer, which is cut to fit and ends the
conversation. Once the model calls no tool, its last words are posted as the
run's user, where the delivery or the run is; save commits only once each
test has passed. The battery holds the same conversation, so what it measures
is this agent when the run's --system is the battery's words and its tools
the checkout's group. Its first proof is three runs of a pattern run/gemma,
written on the server, on one saved task, each with the correct change,
passing checks, a reply on the record and the full exchange within budget,
the smallest Gemma that passes named exactly; score the failures too. Trunk's
fuller prompt passed 7 of 16 trials against 4 of 16 for the terse one, so
Parsimony means the shortest sufficient prompt, measured by the task; its
192-step default, ambient configuration and local-only logs are not the
target. Once such a pattern is written, a person can hand a local model a
subtask with create --to POST in the delegating agent's thread, naming the
pattern and a user of the model's own; this is not yet tried.
An agent's MCP surface (built on branch agent-tools, decisions 65 to
67; docs/agent-tools-proposal.md says why each
is shaped as it is, and the battery, battery/main.cr, measures them with
local models, its runs Fossil tech-notes). Tools bound to the run's own
checkout, served to its process:
| Tool | Result and boundary |
|---|---|
ocx_context |
The run, its objective, its working branch, its unsaved files and its tests. |
ocx_find, ocx_read |
A text's lines, and a file's lines exactly, bounded, from the run's checkout; never a database or a secret. |
ocx_edit |
Text that appears once replaced, or added at a file's end. |
ocx_test |
The project's tests, named in its checkout, their output bounded. |
ocx_save |
A check-in on the run's own agent/ branch, once each test has passed; never a merge or a verdict. |
ocx_wiki_read, ocx_wiki_edit, ocx_unversioned_list, ocx_unversioned_get, ocx_unversioned_put |
Wiki pages and shared binaries. |
ocx_post |
An answer where the run is, as its user. |
ocx_thread |
What was said where the run is: each post or ticket change, with who sent it, read from the run's clone. |
The native agent and the battery are offered the checkout's group: every
tool above but ocx_post and ocx_thread, which a run's MCP serves; the
native agent posts its last words itself. A run's MCP offers every tool its
user may call, not only these; the battery offers only the checkout's group,
so what it measures holds for that surface alone until it measures the whole.
Agents that cannot hold a key (built on branch mcp-tunnel, decisions
58 to 60). Some agents run where
their provider will not let them keep a Fossil password. An inbound pattern,
run/mcp-tunnel, is a proxy to one such agent: an admin starts one run of
it per remote agent, on an agent machine; its process is the provider's
tunnel client, which connects out, with no inbound port opened, and OCX's MCP
tools served over HTTP on the sandbox's own localhost; the run's user is the
agent's identity, so the agent's posts, verdicts and check-ins go through the
run's clone as that user, and it never holds the password (the maintainer,
2026-10-14: "run/mcp-tunnel is the way to make a proxy to a remote agent").
An agent that edits its own clone brings its check-ins as a bundle through
sync (decision 58). Still to show: an agent's check-in landing through the
tunnel.
Agents send runs (built on branch agent-tools, decisions 62, 75 and 81).
An agent is limited as any user is, by the Fossil capabilities an admin
gives it on the Users page. A user holding R may send runs, such as a
build to a build machine, and stop the runs it sent; each node takes such a
run only within what its owner allows, in a file of the release it runs, and
refuses one asking more, naming what it asked (USAGE.md, "Let
an agent send runs"). An agent writes one from inside its run with create
in its run's clone, pulled and pushed, such as the build of its check-in,
and a session whose ends is true is given the build's ended (decision 87).
The maintainer, 2026-10-14: "we should be able to restrict that agent the
same way we restrict other agents--through the capabilities we set for it";
2026-10-16, through cleave's session: "get me a way to run build jobs. it
ain't rocket science."
Who may do what. Fossil's capabilities
set the outer limits: a user holding admin or setup sends a run or a stop,
and one holding R sends a run within what the node's owner allows, and a
stop for a run it sent (HISTORY.md decision 75); a run's user
holds check-in and forum writing, never admin or setup; a node user holds
goC4w, never admin or setup, with i for verdicts and y for shares
(Fossil, senders and nodes, section 3).
i admits any write, so OCX's tools and separate users, not Fossil, tell an
agent's, a check's and a reviewer's acts apart.
Parity contract
The maintainer has not yet chosen which branch merges into which, nor which functions that merge must carry; docs/parity-v1.md lists what trunk did. The gate stays red until the scope is written here as rows, each with a check-in on this branch and a live demonstration the maintainer reviewed.
| Behaviour | Check-in | Demonstration | Status |
|---|---|---|---|
| Merge target and required subset chosen on the record | — | Record the decision and the demonstrated check-ins for the selected functions here. | open |
Phases
In the maintainer's order of 2026-10-14:
- Clean up and check the design. One place for each topic (HISTORY.md decisions 46 to 49), then the battery's readers, rebuilt on this design, read all of it to see how well the clean-up went.
- MCP, and the bridge for agents that cannot hold a key. The agent's MCP surface above, reached through the providers' tunnels.
terminalandattach. A long session a person joins at its node: both built (decisions 82 and 83).- The native agent for local models, to its first proof.
- More from parity and the roadmap: docs/parity-v1.md's remaining order, then ROADMAP.md.
- Compare branches before merging. Decide with live evidence which of trunk's remaining functions improve the product, record the deferrals, and fill the parity contract.
Working rules
- A unit is a slice, never a file. The first unit of a phase is the thinnest end-to-end slice that achieves the phase's intent; later units deepen it; types are extracted from working slices, not declared ahead of them. A check-in whose only claim is "here is a file" has no intent.
- Parsimony admission. State the minimal contract and fixed work budget for each slice. A new tool, state file, abstraction or model step earns its place by a demonstrated need in that slice: a scenario's step, or a test that demonstrates a tool. What loses its use is removed, not guarded (the maintainer, 2026-10-08). A Gemma failure prompts inspection of the task and interface before increasing model size or adding machinery.
- Check-in format. Title line; then
Intent:(what for),Expression:(what changed),Demonstrates:(the spec file orcrystal runcommand that shows it, which must exist). Cite any precept in prose or a check-in comment by ID and name, such asprecept C6 (Explicit Arguments). Guards: precept C3 (Stated Change) and precept A1 (Visible Evidence). - One CI command.
crystal run ci.cr: dependency ledger, format check, tree guards and coverage ratchet.-- hostadds the host guards;-- merge-gateadds the parity and compiler gates. On a compiler other than the pin the result says so and is not a gate result. CI and tools take explicit arguments, with only the served CGI request fields excepted by precept C6 (Explicit Arguments). - Audit by sample. A verdict is a tag on the check-in it judges (verdicts); a ticket records work arising from it, so a failing audit usually yields both. Absence means unaudited and is visible; precept A2 (Artifact Audit) prints coverage and the verdicts.
- Decisions. The maintainer carries five to ten decisions a day. Ask only when blocking, one question at a time, on the artifact the work came from; bring every question of scope. Otherwise say what will be done and do it. An idea that would take the work off course goes in docs/backlog.md for review, not into a question.
- Exchanges on the record. Every exact model request, advertised tool schema, raw response and tool result belongs where the run is, whole, in the run's kept standard output, when its process ends; no credential is given to the model, though a test
ocx_testruns can still read the clone's password (docs/backlog.md). From the record's view, a person and an agent differ only by user. - One place for each topic. knowledge-map.json says which document holds what; a topic is written there and linked from anywhere else, and a test record is a Fossil tech-note. Neither a green spec nor an old decision silently changes a document.
- Maintainer-owned host scripts. Agents do not edit
scripts/without approval on the record, as HISTORY.md decision 22 requires. - Name. OCX, everywhere it can be used.
Open design questions and deliberate deferrals
- A run left open: a run whose node went down while it ran is answered
lostwhen a later daemon round starts its next watcher, which takes the free run lock, findstakenand ends what the old lock names; nothing answers for a node that never returns. - Memory limits: a node refuses
memoryuntil it enforces it with a cgroup, which needs the host's cgroup tree and leave to make a group. - Objective test: the README states what OCX is for, but not yet a repeatable threshold for useful coding work. Comparing agents on one task tests substitution; a task that also produces a reviewed change tests usefulness. Choose that benchmark before claiming progress.
- Crystal server replacement: any Crystal replacement for Fossil's server must take the same ownership of the served repository, under precept I4 (Server-Only Writer), and show concurrency, locking and rollback-journal behavior before it opens one.
- Scope of replacement: the README lets Fossil, Crystal and Linux change over time; the guards show only specific seams. A replacement answers a measured need before abstraction is added for it.
- External program wrappers: Fossil's reads pass one contract spec by two
implementations, the program and direct SQLite (
spec/ocx/fossil_spec.cr); its writes and an artifact's content have only the program's so far. - Merge evidence: the gate checks a parity row's status and its check-in's existence, not that the maintainer saw the behavior live; strengthen it once the merge scope is chosen.
- Search storage: trunk keeps a vector cache and unversioned transfer blobs in a repository; reconcile that with precept I4 (Server-Only Writer) before bringing search back.
- Releases beyond a staging server: before a server with private code or costly downtime (HISTORY.md decision 31): the preview as its own OS user; acceptance recorded as an artifact (digest, full check-in, node, user, time), with accept hashing the files; trust across nodes by a key held off the server; reproducible builds; and a per-agent or drop-only staged area.
- Model refinement: prompt conditioning and a few-shot corpus are not weight training; defer any training claim until reproducible evaluations show an improvement over the base model on coding work.