A chat page where the maintainer talks with this project's session about everything they're working on. The maintainer approved this direction on 2026-11-04 (HISTORY.md, "The design to start from"): what they see is board 3's; how it runs on Fossil is swk-ai's.
What it is
- One page, served by this repository as a Fossil extension, as swk-ai is served by its own. Fossil signs the maintainer in.
- The conversation is the session's own forum thread. Each message the maintainer types is a post in it, as them. The session already receives every post there, so the page sends no runs.
- The session answers in the thread, in plain sentences, each record a link. Its first answer of a day opens as board 3 does: what needs the maintainer, what is working, and what waits on an agent, across their projects.
- The page shows the thread as a chat, read from the forum.
Rules it keeps
- From swk-ai: the page's program never writes a file, with one
exemption: Fossil's configuration file, in a directory on a tmpfs (RAM),
since Fossil needs one to render or read. Otherwise it reads the
repository read-only; a message becomes a post through OCX's
post, as swk-ai sends runs through OCX'screate. - It touches OCX only through its tools, so either can change (Loose Coupling).
Reading the record
The maintainer, 2026-11-04, grading swk-ai's code against the virtues:
ocx builds on fossil which builds on sqlite which builds on basic file storage. each level provides greater abstraction/meaning. stability should be measured by our ability to mechanically analyze the previous meanings of data to associate them with meanings we have today. interchanging the tools we use to analyze the data and knowing that we have the opportunity to interchange those tools is what should give us confidence. Aligning to strict versions/builds or putting in unpredictable agents to derive meaning should be avoided.
The ideal code in the case of analyzing Fossil SQLite data stores, in my mind, can use build-time switches to either use the Crystal SQLite library or run a specified Fossil command-line.
So:
- One reader, two ways to build it. Everything the console reads from the repository goes through one wrapper whose methods say what they give (a thread's posts, who wrote each, when). A build-time switch picks how: the Crystal SQLite library, decoding Fossil's artifacts in Crystal, or a named Fossil command line. Both must give the same answers, and a test says so.
- Fossil runs from one call site, and so does OCX's
ocx2. - Posts are rendered by Fossil, as its forum renders them: the
maintainer asked, "what about using fossil's markdown-to-html converter?"
It is
fossil test-markdown-render --safe -, through that one call site. It is a test command, so Fossil doesn't promise its interface;--safekeeps ajavascript:link, which the Content-Security-Policy Fossil sends with every page blocks, as on Fossil's own forum. - At a data boundary, fall back to something meaningful, a layer down, rather than fail or guess.
- A browser test bench on a throwaway repository, beside the specs: the page opened in this session's browser, a message typed, the answer shown.
What ~/.fossil costs, checked 2026-11-04 with Fossil 2.27. Fossil's
command line opens its global configuration file even for fossil sql
--readonly: it creates ~/.fossil when missing, refuses to run when the
home directory isn't writable ("must be writeable"), and refuses when the
file exists but is read-only. A read leaves the file's bytes unchanged. So a
page that must never write a file can run Fossil only with that file given
somewhere writable, such as FOSSIL_HOME on a tmpfs, as swk-ai's one
exemption does for attachments.
Conversations
The maintainer, 2026-11-04: "can I get a hamburger ... to bring up a chat list (able to be left open or closed) with a list of chats and a way to start a new chat?" Asked whether a new conversation should start a new session, they asked for advice, and said yes to it (HISTORY.md, "what the console is for").
- ☰ opens the list of this project's threads, most recently added to first; it stays open or closed as it was left. Choosing one shows it.
- A new conversation is a new session. Its first message is the
objective of a session run, sent as the maintainer with OCX's
create(src/console/session.json says what: the session pattern, x86-1, its clone); the run's thread is the conversation. Sessions share what they know through this repository: each is told to read HISTORY.md, DESIGN.md and SETUP.md first. - A short name for the menu, which the maintainer asked for ("It would
be nice to be able to rename the chats to something more terse"): ✎ beside
a conversation gives it one, a raw Fossil tag
console-nameon its first post. The post, a session's run, never changes; OCX treats a changed run as a new request. An empty name brings the title back. - OCX's messages are said in words on the page: a run as its objective, the node's started and ended in a line. Anything else, or anything the page doesn't recognize, shows as posted.
Images
The maintainer, 2026-11-04: "I notice I cannot paste an image here", then
"I don't love them going to wiki pages, like they do for swk-ai", and yes to
unversioned files. A forum post can't hold a file in Fossil, so an image
pasted or dropped into the message box is stored as an unversioned file of
this repository, images/HASH.EXT (its SHA3-256), and the post links it,
/ocx-console/uv/images/HASH.EXT. The same image twice is one file. Pasting
needs Fossil's write-unversioned capability (y). Clones get the images
with fossil uv sync.
One back end, two hosts
The maintainer, 2026-11-05: "i want to enable richer UIs with the fossil back end for several interfaces, including the media player, the robots compiler, and a bunch of things i forget or haven't thought of yet", and "i don't want to maintain a bunch of swift code when i really want 1 crystal version and to also run on web pages." They want this console on the phone too, deferring Stone's own.
The idea: a back end like this one is built twice from the same Crystal.
Natively, Fossil runs it on a server as its /ext CGI. For WebAssembly
(wasm32-wasi), a phone app such as Stone runs it for its own built-in
Fossil server, the same way: request in the environment and standard
input, page out on standard output. Each app is then Crystal and a page,
with no Swift of its own.
Shown so far (2026-11-05; images and projects 2026-11-06):
crystal run tools/wasm/wasm.cr -- check REPOSITORY: the console's reader, built for wasm, reads a repository in the host and gives the same answer, byte for byte, as the native build. SQLite, zlib (Fossil's compressed artifacts) and PCRE2 (Crystal's regular expressions) build for WASI from their sources.crystal run tools/bench/bench.cr -- --wasm OCX2: the whole console, built for wasm and run by its host as Fossil's extension, passes the browser bench, every step, pasting an image included.
The module asks its host for what WASI can't do, through imports of the
module console_host (src/console/host.cr): projects lists the
repositories the host serves (WASI has no directories), query reads one,
fossil runs a Fossil command (writes, Markdown), with a file the host
writes from the request's bytes when the command takes one (an image),
ocx2 runs OCX's ocx2 (posts, new conversations). It never opens the repository itself: WASI has
no file locks, so a read could see half of a sync's commit (x86-1-stone,
forum ec4d48141e). tools/wasm/host.cr is such a host on Linux, embedding
WAMR (the WebAssembly Micro Runtime, which also runs on iOS), built from
source as an interpreter. Stone runs a module before its Fossil, not
inside it: the Fossil lock isn't recursive.
Not yet:
- Posting on a phone, which can't run
ocx2. Decided: "ocx would expose it as a library, since it owns the protocol definition" (the maintainer, 2026-11-05). The console would compose a post with OCX's library and store it through the host'sfossil, as Stone stores replies. Only starting a session would still needocx2, since that reaches the server. Asked of OCX's session at forum post 5b1d523475. - The phone's half (running a wasm module for its Fossil server) is Stone's session's work. iOS allows no just-in-time compiling, so it would be an interpreter; and Apple limits apps running code they download, so modules synced from a repository need checking against App Review's rules.
How it will be shown to work
First with a throwaway repository and a stand-in for OCX, as swk-ai's tests do. Then live: the maintainer types a question on the page, and the session's answer appears there.
Not yet
Buttons that act, following the session's steps live, and anything else board 3 shows beyond the conversation. Each comes after the conversation works, and only if the maintainer wants it.
Open, one at a time
- ~~Start from swk-ai's code?~~ Settled: its storage decoding is ported; the reader, the rendering and the page follow "Reading the record" instead.
- ~~Which projects the session reads~~: every project on ollama.openbeagle.org (the maintainer, 2026-11-04, 11:54 PM). How it gets read access to each is still open.
- ~~The page's address~~:
/ext/consoleunder this repository, the maintainer's own word.
Other projects
The maintainer, 2026-11-05: "the writes should be going to the other forums and I should be able to chat with the other sessions already live on those forum threads".
The console lists the repositories beside its own on the Fossil server. Choosing a project shows its forum threads and sends replies there as the signed-in user, with that repository's permissions. Pasted images stay in the console's repository and work in any project's posts.
Not yet: new conversations and names are only for this project. Projects on other servers are not yet available.
Which sessions are active
The maintainer, 2026-11-05: "I have no visual indicator in this console
that any of the sessions are active or how loaded the machines are where
they run." The menu says, under each conversation, whether its session is
running or waiting to start, from OCX's status on that project's
repository, as the person signed in: its open runs, from the record. If OCX
can't say, the menu shows nothing about it.
Not yet: how loaded the machines are. OCX's record doesn't hold that; only a node's own host sees its processes.