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 in the question shape (question, references, optional options and stakes); 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 the server's host or on another. The node
builds all of it but terminal, which it refuses, saying so, until it is
built. 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 | A node acts when artifacts arrive, from the server's hook or a pull on another host; nothing polls. |
| Distributed work | built | ocx2 node on a host's clone. Still to show live: a build machine or lab board running a run and its reports 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, which needs terminal and attach. |
| Local models: the native agent | missing | OCX's own program for a local model, below. Trunk's Ollama loop and four-task battery are starting evidence: gemma4_31b and codex-crystal-gemma4 passed 5 of 8 trials. |
| Visible model exchanges | missing | Each exact request and response of the native agent, with the advertised tool schemas and each tool result, posted where the run is before the next step. |
| An agent's MCP surface | planned | The bounded tools below, for an agent's own work in its run. |
| Agents that cannot hold a key | planned | A bridge to OpenAI's Secure MCP Tunnel, and perhaps Anthropic's MCP tunnels, so such an agent's contributions are saved with no inbound port opened (the maintainer, 2026-10-14). To design next. |
| 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; a ci verdict from a check's session is missing, as is a local model's cited review report beside a distinct user's verdict. |
| 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 (to settle). OCX's own program, named as a run's command, so the protocol stays agent-free: it reads its run and a delivery on its standard input and works in its run's checkout, talking to a local model through Ollama at an address its run's environment gives. Start with five tools: inspect, bounded read, patch, verify and finish; add one only when a task shows it is needed. Give one saved edit task a fixed step and byte budget. Post each exact request and response JSON, the advertised schemas and each tool result where the run is before the next model step; keep credentials out of every request, and refuse an unsafe or oversize exchange before sending rather than truncate the record after. Commit only once verify passes. Choose the smallest Gemma that can do the task and record its exact identity. Its first proof is three independent runs of the saved task, each with the correct change, passing checks, a reply on the record and the full exchange within budget; 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.
An agent's MCP surface (to settle). Tools bound to the run an agent works in, served to its process:
| Tool | Result and boundary |
|---|---|
ocx.context |
The run, its objective and what it has been given. |
ocx.read |
A bounded excerpt of the record, the source or a diff, from the run's clone; never a database or a secret. |
ocx.edit |
A validated patch to the run's checkout. |
ocx.check |
A named, allowed check, its output bounded and its use metered. |
ocx.report |
An answer or a cited review report where the run is, as its user. |
ocx.delegate |
A bounded subtask: a run of the native agent under its own run user. |
ocx.propose |
A change on the run's work branch, naming the branch it aims to advance; never a merge or a verdict. |
The native agent starts with the first five; delegation and proposal come only when a task needs them.
Agents that cannot hold a key (next to build). 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 the server's node; 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. Steps: MCP over
HTTP beside stdio; the pattern, its sandbox opening only the tunnel's
network; then a ChatGPT agent posting on a cleave thread through it, the post
showing as its user (the maintainer, 2026-10-14: "run/mcp-tunnel is the way
to make a proxy to a remote agent").
Agents send runs (decided, to build). An agent is limited as any user
is, by the Fossil capabilities an admin gives it on the Users page; sending
runs is one of them, a capability an admin grants to the agents that may
send runs, such as a build through an outbound pattern like cleave's
run-aarch64.md (which letter, and whether Fossil keeps one it does not
define, is to settle). A run such an agent sends from inside its own run sees
no more of the host than that run: the same paths or fewer, and the network
only if its own run has it (the maintainer, 2026-10-14: "sure", and "we
should be able to restrict that agent the same way we restrict other
agents--through the capabilities we set for it").
Who may do what. Fossil's capabilities
set the outer limits: only a user holding admin or setup sends a run or a
stop; a run's user holds check-in and forum writing, never admin or setup; a
node's user holds none on the server, or o and i on another host
(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.- 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, before the next model step; no credential enters that exchange. 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
lostonly when that node starts again or its administrator runs the check; 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.