Login
View Ticket
Login
Ticket Hash: 29062db5de97d5673a595d72e4948c41bd6a1543
Title: Gemma milestone 1: one watched run of run/gemma
Status: Open Type: Feature
Severity: Priority:
Subsystem: Resolution:
Last Modified: 2026-11-09 05:51:06
2.1 days ago
Created: 2026-11-09 05:47:03
2.1 days ago
Version Found In:
Description:
Gemma milestone 1 (go: ocx-console post 40e2e11e8b; pattern: wiki run/gemma, saved by stone 2026-11-09 12:39 AM Eastern). Run 1: gemma4:31b with the battery's system words. Run 2: the same model with the old prompt (models/codex-crystal-gemma4.system.md at tag ollama-codex) as --system. Each Gemma check-in gets an audited verdict.
User Comments:
stone added on 2026-11-09 05:49:06:
{
  "ocx": 2,
  "to": "x86-1",
  "run": {
    "workspace": [
      {
        "step": "directory",
        "at": "$$root$$/$$process_user$$/projects/$$repository_name$$/$$run$$"
      },
      {
        "step": "password"
      },
      {
        "step": "clone",
        "into": "$$workspace$$/clone"
      },
      {
        "step": "checkout",
        "of": "trunk",
        "into": "$$workspace$$/tree"
      }
    ],
    "sandbox": {
      "uid": 1000,
      "gid": 1000,
      "linux_capabilities": [],
      "network": true,
      "isolate_terminal": true,
      "ends_with_parent": true,
      "read_only": [
        "/usr",
        "/bin",
        "/sbin",
        "/lib",
        "/lib64",
        "/etc/resolv.conf",
        "/etc/hosts",
        "/etc/nsswitch.conf",
        "/etc/ssl/certs",
        "$$release$$"
      ],
      "read_write": [
        "$$workspace$$"
      ],
      "homes": [],
      "created_files": [
        {
          "at": "/etc/passwd",
          "text": "$$process_user$$:x:1000:1000::$$workspace$$:/bin/sh\n"
        }
      ],
      "proc": "/proc",
      "dev": "/dev",
      "tmp": "/tmp"
    },
    "limits": {
      "wall": "2h"
    },
    "process": {
      "command": [
        "$$release$$/ocx2",
        "--mcp-ollama",
        "http://127.0.0.1:11434",
        "--model",
        "gemma4:31b",
        "--steps",
        "40",
        "--system",
        "You work on a project's files through the tools you are given. Start with ocx_context. Read a file before you edit it, and copy the text to replace exactly from what ocx_read gives. Run each test with ocx_test before ocx_save. When the objective is met, stop calling tools and say so in one line."
      ],
      "cwd": "$$tree$$",
      "keep": {
        "stdout": "1M",
        "stdout_when": "always",
        "stderr": "1K"
      },
      "env": {
        "HOME": "$$workspace$$",
        "USER": "$$process_user$$",
        "PATH": "$$release$$:/usr/local/bin:/usr/bin:/bin"
      },
      "user": "run-66700aad"
    },
    "objective": "In PLAN.md, the table row \"Local models: the native agent\" ends with the sentence \"Still to show: the pattern `run/gemma` on the server and its first proof.\" Replace that sentence with \"The pattern [`run/gemma`](https://ollama.openbeagle.org/ollama/wiki?name=run/gemma) is on the server; its first proof is still to show.\" Change nothing else. Run the tests, then save, with a comment that is a title line, then paragraphs beginning Intent:, Expression: and Demonstrates:.",
    "clone": "fa361107a96cf737cbba73269a20490cf7b227ff"
  }
}

x86-1 added on 2026-11-09 05:49:23:
{
  "ocx": 2,
  "re": "9a9cacf9760e6107e97635d2bfbb14cd8657e8c63b48da4c09c9ce386df6f117",
  "started": {
    "values": {
      "root": "/var/lib/ocx/agents-daemon/agents",
      "repository_name": "ollama",
      "process_user": "run-66700aad",
      "run": "9a9cacf9760e6107e97635d2bfbb14cd8657e8c63b48da4c09c9ce386df6f117",
      "clone_user": "x86-1",
      "server_url": "https://ollama.openbeagle.org/ollama",
      "release": "/var/lib/ocx/agents-daemon/197a37c0d8ae",
      "releases": "/var/lib/ocx/agents-daemon",
      "workspace": "/var/lib/ocx/agents-daemon/agents/run-66700aad/projects/ollama/9a9cacf9760e6107e97635d2bfbb14cd8657e8c63b48da4c09c9ce386df6f117",
      "process_clone": "/var/lib/ocx/agents-daemon/agents/run-66700aad/projects/ollama/9a9cacf9760e6107e97635d2bfbb14cd8657e8c63b48da4c09c9ce386df6f117/clone",
      "tree": "/var/lib/ocx/agents-daemon/agents/run-66700aad/projects/ollama/9a9cacf9760e6107e97635d2bfbb14cd8657e8c63b48da4c09c9ce386df6f117/tree",
      "checkin": "c92c191591920224defda1ee123fa072e4c7740d234f6da67a47f58538be4660"
    },
    "limits": {
      "wall": "2h"
    }
  }
}

run-66700aad added on 2026-11-09 05:51:06:

The sentence in PLAN.md has been updated as requested. I ran the tests (which returned no tests defined for the project) and then saved the change with the required comment format.

Update run/gemma status in PLAN.md Intent: Update the status of the run/gemma pattern in PLAN.md to reflect that it is on the server. Expression: Updated a sentence in PLAN.md in the "Local models: the native agent" table row. Demonstrates: The table row for "Local models: the native agent" in PLAN.md now contains the updated sentence with a link to the run/gemma wiki page.


x86-1 added on 2026-11-09 05:51:06:
{
  "ocx": 2,
  "re": "9a9cacf9760e6107e97635d2bfbb14cd8657e8c63b48da4c09c9ce386df6f117",
  "ended": {
    "outcome": "exited",
    "exit": 0,
    "outputs": []
  }
}

x86-1 added on 2026-11-09 05:51:06:

The process for the run 9a9cacf9760e6107e97635d2bfbb14cd8657e8c63b48da4c09c9ce386df6f117 exited 0.

{"sent":"{\"model\":\"gemma4:31b\",\"messages\":[{\"role\":\"system\",\"content\":\"You work on a project's files through the tools you are given. Start with ocx_context. Read a file before you edit it, and copy the text to replace exactly from what ocx_read gives. Run each test with ocx_test before ocx_save. When the objective is met, stop calling tools and say so in one line.\"},{\"role\":\"user\",\"content\":\"In PLAN.md, the table row \\\"Local models: the native agent\\\" ends with the sentence \\\"Still to show: the pattern `run/gemma` on the server and its first proof.\\\" Replace that sentence with \\\"The pattern [`run/gemma`](https://ollama.openbeagle.org/ollama/wiki?name=run/gemma) is on the server; its first proof is still to show.\\\" Change nothing else. Run the tests, then save, with a comment that is a title line, then paragraphs beginning Intent:, Expression: and Demonstrates:.\"}],\"tools\":[{\"type\":\"function\",\"function\":{\"name\":\"ocx_context\",\"description\":\"Say what you are working on, first: the run's objective, if this is a run's checkout; the branch save commits on; the files changed and not saved; and the tests test may run. Then find and read files, change them with edit, run every test, and save. Needs any of the Fossil capabilities o (check-out).\",\"parameters\":{\"type\":\"object\",\"properties\":{\"dry_run\":{\"type\":\"boolean\",\"description\":\"say what the tool would do now, changing nothing: its checks run, and its changes are only listed\"}},\"required\":[],\"additionalProperties\":false}}},{\"type\":\"function\",\"function\":{\"name\":\"ocx_find\",\"description\":\"Find each line holding a text, exactly as written, case and all, in the checkout's files or under one path: its file, its line number and the line. Then read the file from a little before that line. Needs any of the Fossil capabilities o (check-out).\",\"parameters\":{\"type\":\"object\",\"properties\":{\"text\":{\"type\":\"string\",\"description\":\"the text to find, exactly as it is written in the file\"},\"path\":{\"type\":\"string\",\"description\":\"a file or directory to search under, by its path from the checkout's root; the whole checkout when absent\"},\"dry_run\":{\"type\":\"boolean\",\"description\":\"say what the tool would do now, changing nothing: its checks run, and its changes are only listed\"}},\"required\":[\"text\"],\"additionalProperties\":false}}},{\"type\":\"function\",\"function\":{\"name\":\"ocx_read\",\"description\":\"Read a file of the checkout: up to 200 lines from a line you name, exactly as they are, as text, with the numbers of its first and last lines and how many lines the file has. Copy what edit replaces from this text. Needs any of the Fossil capabilities o (check-out).\",\"parameters\":{\"type\":\"object\",\"properties\":{\"path\":{\"type\":\"string\",\"description\":\"the file, by its path from the checkout's root\"},\"from\":{\"type\":\"integer\",\"description\":\"the number of the first line to read, from 1; 1 when absent\"},\"dry_run\":{\"type\":\"boolean\",\"description\":\"say what the tool would do now, changing nothing: its checks run, and its changes are only listed\"}},\"required\":[\"path\"],\"additionalProperties\":false}}},{\"type\":\"function\",\"function\":{\"name\":\"ocx_edit\",\"description\":\"Change a file of the checkout: replace the text `old`, copied exactly from read's answer, with `new`. `old` must appear in the file exactly once; with `old` empty, add `new` at the file's end, making the file if there is none. It answers the changed lines as read does. Needs any of the Fossil capabilities i (check-in).\",\"parameters\":{\"type\":\"object\",\"properties\":{\"path\":{\"type\":\"string\",\"description\":\"the file, by its path from the checkout's root\"},\"old\":{\"type\":\"string\",\"description\":\"the text now in the file that you replace, copied exactly from read's text, with no + or - marks of a diff; empty to add new at the file's end\"},\"new\":{\"type\":\"string\",\"description\":\"the text to put in its place, as it should read, with no + or - marks of a diff\"},\"dry_run\":{\"type\":\"boolean\",\"description\":\"say what the tool would do now, changing nothing: its checks run, and its changes are only listed\"}},\"required\":[\"path\",\"old\",\"new\"],\"additionalProperties\":false}}},{\"type\":\"function\",\"function\":{\"name\":\"ocx_test\",\"description\":\"Run the project's tests in the checkout as it is now, all, or one by the name the context tool lists: whether each passed, and the last 100 lines it wrote. The save tool needs every test to pass after your last edit. Needs any of the Fossil capabilities i (check-in).\",\"parameters\":{\"type\":\"object\",\"properties\":{\"name\":{\"type\":\"string\",\"description\":\"one test's name, exactly as context lists it; leave it out to run every test\"},\"dry_run\":{\"type\":\"boolean\",\"description\":\"say what the tool would do now, changing nothing: its checks run, and its changes are only listed\"}},\"required\":[],\"additionalProperties\":false}}},{\"type\":\"function\",\"function\":{\"name\":\"ocx_save\",\"description\":\"Commit and push every change once every test has passed since your last edit: on your working branch, with a title and Intent, Expression and Demonstrates lines, as your user. It answers the check-in and who the server says sent it; with nothing changed, it pushes what is unsent. Needs any of the Fossil capabilities i (check-in).\",\"parameters\":{\"type\":\"object\",\"properties\":{\"title\":{\"type\":\"string\",\"description\":\"what the check-in does, in one line\"},\"intent\":{\"type\":\"string\",\"description\":\"why it was made: what asked for it, in one line\"},\"expression\":{\"type\":\"string\",\"description\":\"what changed, and where, in one line\"},\"demonstrates\":{\"type\":\"string\",\"description\":\"the test that shows it works, in one line\"},\"dry_run\":{\"type\":\"boolean\",\"description\":\"say what the tool would do now, changing nothing: its checks run, and its changes are only listed\"}},\"required\":[\"title\",\"intent\",\"expression\",\"demonstrates\"],\"additionalProperties\":false}}},{\"type\":\"function\",\"function\":{\"name\":\"ocx_wiki_read\",\"description\":\"Read a wiki page as the server holds it now, by its name: its text and its version. Change it with wiki_edit. Needs any of the Fossil capabilities j.\",\"parameters\":{\"type\":\"object\",\"properties\":{\"name\":{\"type\":\"string\",\"description\":\"the page's name, as Fossil's wiki names it\"},\"dry_run\":{\"type\":\"boolean\",\"description\":\"say what the tool would do now, changing nothing: its checks run, and its changes are only listed\"}},\"required\":[\"name\"],\"additionalProperties\":false}}},{\"type\":\"function\",\"function\":{\"name\":\"ocx_wiki_edit\",\"description\":\"Change a wiki page as edit changes a file: replace `old`, copied exactly from wiki_read's answer, with `new`; `old` must appear exactly once in the page now, so no newer change is lost. With `old` empty, append `new`, making the page if none. It answers the new text and version. Needs any of the Fossil capabilities k.\",\"parameters\":{\"type\":\"object\",\"properties\":{\"name\":{\"type\":\"string\",\"description\":\"the page's name, as Fossil's wiki names it, not a path\"},\"old\":{\"type\":\"string\",\"description\":\"the text now in the page that you replace, copied exactly from wiki_read's text, with no + or - marks of a diff; empty to add new at the page's end\"},\"new\":{\"type\":\"string\",\"description\":\"the text to put in its place, as it should read\"},\"dry_run\":{\"type\":\"boolean\",\"description\":\"say what the tool would do now, changing nothing: its checks run, and its changes are only listed\"}},\"required\":[\"name\",\"old\",\"new\"],\"additionalProperties\":false}}},{\"type\":\"function\",\"function\":{\"name\":\"ocx_unversioned_list\",\"description\":\"List the unversioned files the server shares, such as binaries: each name, the hash of its content and its size. Needs any of the Fossil capabilities o (check-out).\",\"parameters\":{\"type\":\"object\",\"properties\":{\"dry_run\":{\"type\":\"boolean\",\"description\":\"say what the tool would do now, changing nothing: its checks run, and its changes are only listed\"}},\"required\":[],\"additionalProperties\":false}}},{\"type\":\"function\",\"function\":{\"name\":\"ocx_unversioned_get\",\"description\":\"Get an unversioned file the server shares, by its name: its content, base64, and the hash of its content. Needs any of the Fossil capabilities o (check-out).\",\"parameters\":{\"type\":\"object\",\"properties\":{\"name\":{\"type\":\"string\",\"description\":\"the file's name, as unversioned_list gives it\"},\"dry_run\":{\"type\":\"boolean\",\"description\":\"say what the tool would do now, changing nothing: its checks run, and its changes are only listed\"}},\"required\":[\"name\"],\"additionalProperties\":false}}},{\"type\":\"function\",\"function\":{\"name\":\"ocx_unversioned_put\",\"description\":\"Share a file, such as a binary, as an unversioned file of the server: its name and its content, base64. To change one, give the hash you last saw, so no newer one is lost. It answers the new hash. Needs any of the Fossil capabilities y (write-unversioned).\",\"parameters\":{\"type\":\"object\",\"properties\":{\"name\":{\"type\":\"string\",\"description\":\"the file's name\"},\"content\":{\"type\":\"string\",\"description\":\"its content, base64\"},\"replaces\":{\"type\":\"string\",\"description\":\"the hash of the version it replaces, as unversioned_list gave it; absent or empty for a new file\"},\"dry_run\":{\"type\":\"boolean\",\"description\":\"say what the tool would do now, changing nothing: its checks run, and its changes are only listed\"}},\"required\":[\"name\",\"content\"],\"additionalProperties\":false}}}],\"stream\":false}","received":"{\"model\":\"gemma4:31b\",\"created_at\":\"2026-11-09T05:49:27.255866725Z\",\"message\":{\"role\":\"assistant\",\"content\":\"\",\"thinking\":\"The objective is to update a specific sentence in `PLAN.md`.\\n\\n1.  Read `PLAN.md` to find the exact text to be replaced.\\n2.  Perform the replacement.\\n3.  Run tests.\\n4.  Save the changes with the specified comment format.\",\"tool_calls\":[{\"id\":\"call_hs2f6ryi\",\"function\":{\"index\":0,\"name\":\"ocx_context\",\"arguments\":{}}}]},\"done\":true,\"done_reason\":\"stop\",\"total_duration\":3624328369,\"load_duration\":273721419,\"prompt_eval_count\":2250,\"prompt_eval_duration\":893663168,\"eval_count\":75,\"eval_duration\":2360103745}"}
{"name":"ocx_context","arguments":{},"text":"ok: true\ntool: context\ndry_run: false\nresult:\n  objective: In PLAN.md, the table row \"Local models: the native agent\" ends\n      with the sentence \"Still to show: the pattern `run/gemma` on the server\n      and its first proof.\" Replace that sentence with \"The pattern\n      [`run/gemma`](https://ollama.openbeagle.org/ollama/wiki?name=run/gemma)\n      is on the server; its first proof is still to show.\" Change nothing else.\n      Run the tests, then save, with a comment that is a title line, then\n      paragraphs beginning Intent:, Expression: and Demonstrates:.\n  branch: agent/run-66700aad-661eee85\n  changed: none\n  tests: none\ntook_ms: 53.8\nlog:\n  - read_context\n    changes: false\n","refused":false}
{"received":"{\"model\":\"gemma4:31b\",\"created_at\":\"2026-11-09T05:49:29.214957498Z\",\"message\":{\"role\":\"assistant\",\"content\":\"\",\"thinking\":\"I need to edit `PLAN.md`. I'll start by reading the file to find the exact text to replace.\",\"tool_calls\":[{\"id\":\"call_szzirzwz\",\"function\":{\"index\":0,\"name\":\"ocx_read\",\"arguments\":{\"path\":\"PLAN.md\"}}}]},\"done\":true,\"done_reason\":\"stop\",\"total_duration\":1900898371,\"load_duration\":249023386,\"prompt_eval_count\":2482,\"prompt_eval_duration\":113537633,\"eval_count\":47,\"eval_duration\":1468662424}"}
{"name":"ocx_read","arguments":{"path":"PLAN.md"},"text":"ok: true\ntool: read\ndry_run: false\nresult:\n  text:\n```\n# OCX plan\n\nWhat OCX is for, the precepts that guard it, what is still missing, and the\norder of the work. [README.md](README.md) holds the axioms and virtues;\n[knowledge-map.json](knowledge-map.json) says which document holds each\nother topic. When this plan and the documents it points to disagree, they\ngovern and this plan is corrected.\n\n## What it is for\n\nOCX gets coding work done by people and agents together, with every step on\na Fossil record that anyone with access can read later.\n\n* A task has one hash: a ticket or a forum thread. Its specification,\n  questions, progress, evidence and result stay together on that record.\n* Any agent can take the task: a person in the browser, a hosted agent such\n  as Claude or Codex, or a local model such as Gemma, whose lower reasoning\n  OCX tolerates by bounding what each step asks of it (the maintainer,\n  834ceded37: \"collaborate with agents in ways that makes them efficient and\n  tolerates lower reasoning\"). Each works to the same task and report\n  contract, and each result names the user that produced it, so agents can be\n  compared on the same saved tasks.\n* Each change states its intent, how it is expressed and what demonstrates\n  it. CI and independent reviewers attach their verdicts to that check-in.\n* Acceptance stays with a person: merging and serving a release are\n  explicit, attributed actions, and a release can be rolled back.\n\n## Precepts\n\nEach precept is a testable consequence of a README axiom and virtue. The\nexisting IDs remain stable for their guards: `C` derives from **Clarity**\n(README axioms 2 and 3), `I` from **Loose Coupling** (axioms 1 and 5), and\n`A` from **Demonstrability** (axioms 1 and 4). The latter two prefixes retain\nthe older names Interchangeability and Accountability; they do not introduce\nextra axioms or virtues. **Parsimony** (axioms 1 and 4) also shapes precepts C1\n(File Boundedness), C7 (Pinned Interfaces), and I7 (Single Process Site): each\nbounds a different source of needless complexity. A precept without a guard\nspec is a memory, not a mechanism. The ledger spec fails when a precept has no\nspec tagged `# precept: <id>`.\n\nThe cooperative premise in Axiom 3 is not a security assumption. Axioms 4 and\n5 account for fallibility and the consequences of integration, so the derived\ncontrols remain necessary: precept I4 (Server-Only Writer) limits access to the\nserved repository, precept I6 (Pluggable Confinement) specifies a replaceable\nconfinement mechanism, and precept A2 (Artifact Audit) records review verdicts.\n\nConflict check, done before admission:\n\n- Precept C2 (Single Owner) and precept I4 (Server-Only Writer) agree: the\n  repository owns durable facts, while ephemeral facts stay outside it.\n- Precept I1 (Runner Isolation) and precept I4 (Server-Only Writer) agree: a\n  runner's clone is its own.\n- Precept A4 (Staged Deployment) and precept I4 (Server-Only Writer) agree:\n  deployment does not write a repository.\n- Precept A2 (Artifact Audit) and precept C2 (Single Owner) agree: an audit\n  is a tag on the check-in it judges, not a config row.\n\nNo precept requires an agent to open a served repository, so precept I4\n(Server-Only Writer) has no exception.\n\n| Id | Name | README virtue | If … then … | Guard |\n| --- | --- | --- | --- | --- |\n| **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 |\n| **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 |\n| **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 |\n| **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 |\n| **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 |\n| **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](https://ollama.openbeagle.org/ollama/forumpost/7242762209)), and of the rest only their names. | spec/guards/environment_spec.cr |\n| **C7** | Pinned Interfaces | Clarity, Parsimony | If an interface is to be relied on, then it is listed in [docs/interfaces.md](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 |\n| **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 |\n| **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 |\n| **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 |\n| **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 |\n| **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 |\n| **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 |\n| **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 |\n| **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 |\n| **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 |\n| **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 |\n| **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 |\n| **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 |\n\nHost guards for precept I4 (Server-Only Writer), precept I5 (Rollback\nJournal), and precept A4 (Staged Deployment) live under `spec/host/`, tagged\n`host`, and run with `crystal run ci.cr -- host`; a bare `crystal spec` runs\nthem too, and tells the truth about the host it runs on. They take nothing from configuration: the served\ndirectory and the served CGI root are read from the running Fossil server's own\ncommand line (`--repolist`, `--extroot`), and when no server runs here they are\npending with that reason, never silently green. On 2026-09-21 they failed on\nthe live host: three served repositories were in WAL mode, migrated in place\nthe next day, and the served CGI links resolved into a checkout. Precept A4\n(Staged Deployment) judges OCX's own link; trunk's stand until the maintainer\ntakes them down ([HISTORY.md](HISTORY.md) decision 17).\n\n## Where it stands\n\n[Protocol v1](docs/protocol-v1.md)'s definition is stable: a person or\nprogram asks a node to run a process, talks with it, learns how it ended and\nends it, all on the record, on agent machines. The node\nbuilds all of it, a run on a terminal since [HISTORY.md](HISTORY.md)\ndecision 82. What trunk did that\nocx2 still lacks is [docs/parity-v1.md](docs/parity-v1.md); what OCX is meant\nto do past it, and where each stands:\n\n| Function | State | What is missing, and what shows it done |\n| --- | --- | --- |\n| Shared records | built | Runs, stops, reports, deliveries and kept logs on one thread or ticket ([protocol v1, section 3](docs/protocol-v1.md#messages)). |\n| 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. |\n| 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](docs/how-a-post-reaches-an-agent.md)). |\n| 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](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. |\n| 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). |\n| 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](https://ollama.openbeagle.org/ollama/technote/7c2332a567)). Still to show: the pattern `run/gemma` on the server and its first proof. |\n| 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](KEEP.md), \"Seeing what runs, and joining in\"), never a post. |\n| 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. |\n| Agents that cannot hold a key | built | `run/mcp-tunnel`, a bridge to OpenAI's [Secure MCP Tunnel](https://developers.openai.com/api/docs/guides/secure-mcp-tunnels), 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](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](https://platform.claude.com/docs/en/agents-and-tools/mcp-tunnels/overview) are not tried. |\n| 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. |\n| 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](https://ollama.openbeagle.org/ollama/technote/952120c490)). |\n| 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. |\n| Consistent tools | built | Each tool one typed definition across the command line, the CGI page and MCP ([HISTORY.md](HISTORY.md) decisions 32 and 33). |\n| Reversible releases | built | `stage`, `accept`, `rollback`; accepted from the served page on 2026-10-06. Still to show: a rollback there. |\n| 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. |\n| Documentation freshness, model improvement, project context | evaluate | Trunk has candidates; each returns only with evidence of benefit. |\n\n## Agents on protocol v1\n\nHow each kind of agent works through runs. What is marked to settle is a\ndesign for the maintainer to decide before it is built.\n\n**Hosted agents.** How Claude or Codex runs is a pattern's data, never OCX's\ncode ([HISTORY.md](HISTORY.md) decision 40): its program, arguments, sign-in\nand environment in a run's layers. It answers with `ocx2 post` and checks in\nfrom its clone as its run's user.\n\n**The native agent for local models** (built on branch `agent-tools`,\n[HISTORY.md](HISTORY.md) decision 78). OCX's own program, named as a run's\ncommand, so the protocol stays agent-free: `ocx2 --mcp-ollama URL --model\nNAME --steps N --system TEXT`. It reads its run's line and a delivery's on\nits standard input, works in its run's checkout through the checkout's group\nof tools below, every one but `ocx_post` and `ocx_thread`, as MCP serves them\nto its run's user, refusing a call to any other, and talks to the model NAME\nat the Ollama server URL; the model, its words and its budget are the run's\ncommand's arguments, its byte budget the run's own `process.keep.stdout`,\nand its clock the run's `wall`. It takes a run that keeps its standard output\n`always`, and a session only with `deliveries: start`. Each reply is a line\nof JSON on its standard output, printed before any call it asks for runs,\nand each answer a line after it, the first request and every reply exactly;\nno request larger than the run keeps is sent, no line past it printed, and\nno call run without room for its answer, which is cut to fit and ends the\nconversation. Once the model calls no tool, its last words are posted as the\nrun's user, where the delivery or the run is; `save` commits only once each\ntest has passed. The battery holds the same conversation, so what it measures\nis this agent when the run's `--system` is the battery's words and its tools\nthe checkout's group. Its first proof is three runs of a pattern `run/gemma`,\nwritten on the server, on one saved task, each with the correct change,\npassing checks, a reply on the record and the full exchange within budget,\nthe smallest Gemma that passes named exactly; score the failures too. Trunk's\nfuller prompt passed 7 of 16 trials against 4 of 16 for the terse one, so\nParsimony means the shortest *sufficient* prompt, measured by the task; its\n192-step default, ambient configuration and local-only logs are not the\ntarget. Once such a pattern is written, a person can hand a local model a\nsubtask with `create --to POST` in the delegating agent's thread, naming the\npattern and a user of the model's own; this is not yet tried.\n\n**An agent's MCP surface** (built on branch `agent-tools`, decisions 65 to\n67; [docs/agent-tools-proposal.md](docs/agent-tools-proposal.md) says why each\nis shaped as it is, and the battery, `battery/main.cr`, measures them with\nlocal models, its runs Fossil tech-notes). Tools bound to the run's own\ncheckout, served to its process:\n\n| Tool | Result and boundary |\n| --- | --- |\n| `ocx_context` | The run, its objective, its working branch, its unsaved files and its tests. |\n| `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. |\n| `ocx_edit` | Text that appears once replaced, or added at a file's end. |\n| `ocx_test` | The project's tests, named in its checkout, their output bounded. |\n| `ocx_save` | A check-in on the run's own `agent/` branch, once each test has passed; never a merge or a verdict. |\n| `ocx_wiki_read`, `ocx_wiki_edit`, `ocx_unversioned_list`, `ocx_unversioned_get`, `ocx_unversioned_put` | Wiki pages and shared binaries. |\n| `ocx_post` | An answer where the run is, as its user. |\n| `ocx_thread` | What was said where the run is: each post or ticket change, with who sent it, read from the run's clone. |\n\nThe native agent and the battery are offered the checkout's group: every\ntool above but `ocx_post` and `ocx_thread`, which a run's MCP serves; the\nnative agent posts its last words itself. A run's MCP offers every tool its\nuser may call, not only these; the battery offers only the checkout's group,\nso what it measures holds for that surface alone until it measures the whole.\n\n**Agents that cannot hold a key** (built on branch `mcp-tunnel`, decisions\n58 to 60). Some agents run where\ntheir provider will not let them keep a Fossil password. An inbound pattern,\n`run/mcp-tunnel`, is a proxy to one such agent: an admin starts one run of\nit per remote agent, on an agent machine; its process is the provider's\ntunnel client, which connects out, with no inbound port opened, and OCX's MCP\ntools served over HTTP on the sandbox's own localhost; the run's user is the\nagent's identity, so the agent's posts, verdicts and check-ins go through the\nrun's clone as that user, and it never holds the password (the maintainer,\n2026-10-14: \"`run/mcp-tunnel` is the way to make a proxy to a remote agent\").\nAn agent that edits its own clone brings its check-ins as a bundle through\n`sync` (decision 58). Still to show: an agent's check-in landing through the\ntunnel.\n\n```\n  first_line: 1\n  last_line: 200\n  lines: 304\ntook_ms: 1.1\nlog:\n  - read_lines\n    changes: false\n    path: PLAN.md\n    from: 1\n","refused":false}
{"received":"{\"model\":\"gemma4:31b\",\"created_at\":\"2026-11-09T05:49:51.675107695Z\",\"message\":{\"role\":\"assistant\",\"content\":\"\",\"thinking\":\"I have read `PLAN.md`. I need to find the row \\\"Local models: the native agent\\\" and replace the sentence \\\"Still to show: the pattern `run/gemma` on the server and its first proof.\\\" with \\\"The pattern [`run/gemma`](https://ollama.openbeagle.org/ollama/wiki?name=run/gemma) is on the server; its first proof is still to show.\\\"\\n\\nLooking at the `PLAN.md` content:\\nLine 136: `| 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](https://ollama.openbeagle.org/ollama/technote/7c2332a567)). Still to show: the pattern `run/gemma` on the server and its first proof. |`\\n\\nI will now perform the edit.\",\"tool_calls\":[{\"id\":\"call_i900ab6r\",\"function\":{\"index\":0,\"name\":\"ocx_edit\",\"arguments\":{\"new\":\"| 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](https://ollama.openbeagle.org/ollama/technote/7c2332a567)). The pattern [`run/gemma`](https://ollama.openbeagle.org/ollama/wiki?name=run/gemma) is on the server; its first proof is still to show. |\",\"old\":\"| 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](https://ollama.openbeagle.org/ollama/technote/7c2332a567)). Still to show: the pattern `run/gemma` on the server and its first proof. |\",\"path\":\"PLAN.md\"}}}]},\"done\":true,\"done_reason\":\"stop\",\"total_duration\":22453206581,\"load_duration\":238446407,\"prompt_eval_count\":7986,\"prompt_eval_duration\":2367740553,\"eval_count\":600,\"eval_duration\":19421932994}"}
{"name":"ocx_edit","arguments":{"new":"| 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](https://ollama.openbeagle.org/ollama/technote/7c2332a567)). The pattern [`run/gemma`](https://ollama.openbeagle.org/ollama/wiki?name=run/gemma) is on the server; its first proof is still to show. |","old":"| 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](https://ollama.openbeagle.org/ollama/technote/7c2332a567)). Still to show: the pattern `run/gemma` on the server and its first proof. |","path":"PLAN.md"},"text":"ok: true\ntool: edit\ndry_run: false\nresult:\n  text:\n```\n| 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](docs/how-a-post-reaches-an-agent.md)). |\n| 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](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. |\n| 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). |\n| 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](https://ollama.openbeagle.org/ollama/technote/7c2332a567)). The pattern [`run/gemma`](https://ollama.openbeagle.org/ollama/wiki?name=run/gemma) is on the server; its first proof is still to show. |\n| 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](KEEP.md), \"Seeing what runs, and joining in\"), never a post. |\n| 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. |\n| Agents that cannot hold a key | built | `run/mcp-tunnel`, a bridge to OpenAI's [Secure MCP Tunnel](https://developers.openai.com/api/docs/guides/secure-mcp-tunnels), 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](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](https://platform.claude.com/docs/en/agents-and-tools/mcp-tunnels/overview) are not tried. |\n```\n  first_line: 109\n  last_line: 115\n  lines: 304\ntook_ms: 3.1\nlog:\n  - read_whole\n    changes: false\n    path: PLAN.md\n  - write_file\n    changes: true\n    path: PLAN.md\n    bytes: 28733\n","refused":false}
{"received":"{\"model\":\"gemma4:31b\",\"created_at\":\"2026-11-09T05:49:52.93824127Z\",\"message\":{\"role\":\"assistant\",\"content\":\"\",\"tool_calls\":[{\"id\":\"call_4wrvgsah\",\"function\":{\"index\":0,\"name\":\"ocx_test\",\"arguments\":{}}}]},\"done\":true,\"done_reason\":\"stop\",\"total_duration\":1255914160,\"load_duration\":233563476,\"prompt_eval_count\":9256,\"prompt_eval_duration\":598971454,\"eval_count\":10,\"eval_duration\":331199096}"}
{"name":"ocx_test","arguments":{},"text":"ok: false\ntool: test\ndry_run: false\nstopped: the project names no tests\nnext_step: the project names its tests in ocx-tests.json\ntook_ms: 0.1\nlog: none\n","refused":true}
{"received":"{\"model\":\"gemma4:31b\",\"created_at\":\"2026-11-09T05:49:57.489463292Z\",\"message\":{\"role\":\"assistant\",\"content\":\"\",\"thinking\":\"The `ocx_test` call failed because \\\"the project names no tests\\\". The response says \\\"the project names its tests in ocx-tests.json\\\". Let me check if that file exists. Actually, wait, if there are no tests, then they \\\"pass\\\" by default in some contexts, but here it explicitly says `ok: false`.\\n\\nLet me see if `ocx-tests.json` exists.\",\"tool_calls\":[{\"id\":\"call_ovynzna1\",\"function\":{\"index\":0,\"name\":\"ocx_read\",\"arguments\":{\"path\":\"ocx-tests.json\"}}}]},\"done\":true,\"done_reason\":\"stop\",\"total_duration\":4547109280,\"load_duration\":242891184,\"prompt_eval_count\":9331,\"prompt_eval_duration\":69793150,\"eval_count\":113,\"eval_duration\":4079583412}"}
{"name":"ocx_read","arguments":{"path":"ocx-tests.json"},"text":"ok: false\ntool: read\ndry_run: false\nstopped: no file ocx-tests.json\nnext_step: find files with find; a wiki page is no file: read it with wiki_read\n    and change it with wiki_edit, by its name\ntook_ms: 0.2\nlog:\n  - read_lines\n    changes: false\n    path: ocx-tests.json\n    from: 1\n","refused":true}
{"received":"{\"model\":\"gemma4:31b\",\"created_at\":\"2026-11-09T05:50:05.630988342Z\",\"message\":{\"role\":\"assistant\",\"content\":\"\",\"thinking\":\"The user asked me to run the tests. `ocx_test` said \\\"the project names no tests\\\" and suggested `ocx-tests.json`. But `ocx-tests.json` does not exist.\\n\\nLet's check `ocx_context` again to see if any tests are listed.\\nWait, `ocx_context` said `tests: none`.\\n\\nIf there are no tests, then \\\"Run the tests\\\" is effectively a no-op, or I should check if there are any other ways to run tests.\\nThe `ocx_test` tool documentation says: \\\"Run the project's tests in the checkout as it is now, all, or one by the name the context tool lists\\\".\\nSince `ocx_context` lists no tests, I can't run any.\\n\\nLet me try to find if there are any test files in the repository.\",\"tool_calls\":[{\"id\":\"call_jvgth923\",\"function\":{\"index\":0,\"name\":\"ocx_find\",\"arguments\":{\"text\":\"test\"}}}]},\"done\":true,\"done_reason\":\"stop\",\"total_duration\":8138059893,\"load_duration\":251276647,\"prompt_eval_count\":9465,\"prompt_eval_duration\":100214428,\"eval_count\":209,\"eval_duration\":7584128528}"}
{"name":"ocx_find","arguments":{"text":"test"},"text":"ok: true\ntool: find\ndry_run: false\nresult:\n  found:\n    - HISTORY.md\n      line: 135\n      text: 25. The console keeps its state on the record, and only a workspace\n          keeps files. A launch writes the grant (when the record has none) and\n          a note saying who started the session with what on its thread or\n          ticket, as the agent. The console's Sessions list is derived from\n          those notes, and a runner's default grant is the latest on the\n          repository. A session's own state stays in its workspace directory\n          (`~/run`, `launch.log`, `launch.pid`), since a workspace is sandboxed\n          and works with a checkout anyway; the agent's password file stays as\n          decision 24 put it. The public URL a session clones from and writes\n          to is each repository's own `email-url` setting, set by its\n          administrator, and a launch is refused without it. Earlier cuts\n          guessed the URL from the request, three times wrongly, and kept\n          launch files and a saved grant per runner beside the workspaces. The\n          maintainer's words (thread adfc87fba2, 2026-09-23): \"Only the\n          workspaces should be getting state from the filesystem… Fossil is our\n          abstraction to the storage wherever it can handle it\", and \"The\n          email-url config property can be requested to be configured on each\n          repository.\"\n    - HISTORY.md\n      line: 141\n      text: 31. ollama.openbeagle.org is a staging server: its stakes are low\n          (some agent logins and otherwise public data), its work is copied by\n          Fossil's sync on immutable records, and it runs on isolated,\n          untrusted hosts. On it, `ocx2-cgi-next` is the pre-release candidate\n          and `ocx2-cgi` the active release candidate. The preview runs\n          agent-built code as the server's account, by choice, bounded by the\n          CI checks and by which agents are trusted. The web page does not\n          offer `deploy`, which runs the checkout's own code; once a release is\n          served, only the active release accepts, the pre-release candidate\n          accepting only a node's first release, trusted on first use; either\n          rolls back. Before any server holding private code or where downtime\n          is costly, these gate: the preview as a separate OS user (or staging\n          only), since checks enforced by the server's own account guard\n          against mistakes and not a hostile build; acceptance recorded as an\n          artifact holding the release digest, the full check-in, the node, the\n          login and the time, made from the live page, with accept hashing the\n          files itself; trust across nodes by a signature from a key held off\n          the server; reproducible builds, tested by building one check-in\n          twice in different places and comparing; and a per-agent or drop-only\n          staged area in place of a shared one. The maintainer, 2026-10-05, in\n          the session reviewing the CGI, after two outside reviews; this amends\n          decisions 19 and 21 for the `ocx2` branch.\n    - HISTORY.md\n      line: 150\n      text: 40. OCX's code knows no agent. A runner other than `command` is\n          named by the repository's wiki page `sandbox/NAME`, whose program,\n          arguments, home files and environment the node runs: how a program\n          such as Claude or Codex is run, its remote control included, is that\n          page's data, and a run carries no field for it. Every program reads\n          its run, `{\"run\", \"objective\"}`, as the first line of its standard\n          input, and a session then its deliveries, a line of JSON each; a\n          run's `session` alone says how long its program lives, and where a\n          run is posted decides nothing: a task of many forum posts and a\n          ticket's resolution are usage patterns, data in the runs people send.\n          The maintainer at the terminal, 2026-10-12, in turn: \"How an agent\n          takes turns should be dependent on the task. I'd say the more typical\n          approach should be to use terminal sessions with remote control for\n          milestone-class tasks with multiple forum posts in the interaction.\n          And for ticket resolution, a single process per turn should be the\n          approach.\"; of a first form of this decision, which tied the way to a\n          forum thread or a ticket (1016a51a6e): \"Just let the OCX message\n          dictate the life of the session ... That's just a usage pattern and\n          doesn't need to live in the code at all. It is just data.\"; \"Get rid\n          of \"remote\" as an OCX message parameter.\"; and \"there shouldn't be\n          anything claude or codex specific in the CODE ... I don't know what\n          you'd be doing outside of putting in command-line arguments onto the\n          wiki page or putting something in the docs that is claude/codex\n          specific.\" What is agent-specific, parsing a turn's response, live\n          status and SSE, comes after v1 is complete, and Claude- and\n          Codex-specific tests, outside the source (\"I do want claude and codex\n          specific **TESTS**, but not in our source code today\").\n    - HISTORY.md\n      line: 151\n      text: 41. `ci` is no runner but a usage pattern: a session whose\n          `checkins` names the branches, its program checking each check-in it\n          is given in its own clone and recording a `ci` verdict on it as its\n          run's user, from whom alone a `ci` verdict counts. The maintainer at\n          the terminal, 2026-10-12: \"Why is \"ci\" a special runner?\", then\n          \"don't put into code what is just data.\" What the node's own checkout\n          of each check-in attested, that a pass came from a checkout of\n          exactly that check-in, goes with it.\n    - HISTORY.md\n      line: 154\n      text: 44. Protocol v1 is written as tables, and the tables are the\n          standard: [docs/protocol-v1.md](docs/protocol-v1.md), with\n          [docs/protocol-v1-fossil.md](docs/protocol-v1-fossil.md) for what it\n          rests on (Fossil as the medium, finding a message, who sent an\n          artifact, verdicts, nodes, tools and versions). A run is built in\n          layers a node processes outer to inner: workspace, a list of steps;\n          sandbox, every field required; limits; and process, holding the\n          command, its environment, `manual`, the subscriptions, `deliveries`\n          (feed or start), `terminal` and `keep`. A string names something the\n          node knows as `$$name$$`, every other character literal, and\n          `started` records each value; the node adds nothing silently. The\n          maintainer at the terminal, 2026-10-13: \"If we think about the JSON\n          structure like a network packet, our life might get simpler\"; \"Let's\n          not allow any silent adds\"; \"Why not just something like `$$VAR$$`\";\n          \"the terminology in 13 seems mostly fine to me\"; and \"yes to draft\n          being promoted\". Of moving `env` to the process layer and the budget\n          to the limits layer, out of the sandbox object of 62e45fcde6: \"my\n          previous sandbox object approval was just tentative as it looked\n          reasonable. getting it implementable and at the right layer is more\n          important.\" The draft was reviewed by a fresh reader and a spec-only\n          implementer ([docs/review-v1-tables.md](docs/review-v1-tables.md)),\n          and by the battery, tests 20 and 21 (docs/battery/defs, batch 6). The\n          code still follows the definition as it stood at a38dbeafca, though\n          its comments now cite the new sections; [docs/protocol-v1-limits.md](https://ollama.openbeagle.org/ollama/finfo?name=docs/protocol-v1-limits.md)\n          and [docs/protocol-v1-sessions.md](https://ollama.openbeagle.org/ollama/finfo?name=docs/protocol-v1-sessions.md)\n          are kept, marked superseded, until it follows the tables. This amends\n          decision 42's fields.\n    - HISTORY.md\n      line: 158\n      text: 48. Test records live outside the tree. The battery of uninitiated\n          readers, its method, findings, every round's prompts, definitions,\n          answers and transcripts, and the harness that ran them, is removed\n          from the tree and read as it stood at check-in f68b57bd52 ([the battery](https://ollama.openbeagle.org/ollama/doc/f68b57bd52/docs/battery/README.md)),\n          linked from the knowledge map's records kept elsewhere; a new test\n          record is a Fossil tech-note, linked from there. It stays the\n          evidence behind protocol v1's words (decision 44). The maintainer at\n          the terminal, 2026-10-14, in [KEEP.md](KEEP.md)'s words.\n    - HISTORY.md\n      line: 175\n      text: 65. An agent edits a run's own checkout through tools, a weak local\n          model included, with no clone, Fossil or password of its own\n          ([docs/agent-tools-proposal.md](docs/agent-tools-proposal.md)):\n          `context`, `find`, `read`, `edit`, `test` and `save`, and\n          `wiki_read`, `wiki_write`, `unversioned_list`, `unversioned_get` and\n          `unversioned_put`, in a new group of the list, the checkout. A path\n          stays inside the checkout, its links followed to the deepest part\n          that exists; `read` gives text exactly, its line numbers apart;\n          `edit` replaces a text that appears once; the project names its tests\n          in `ocx-tests.json` at its checkout's root; `save` commits on\n          `agent/`, the user and eight hex digits, once each test has passed\n          with exactly the checkout's changes, and pushes as the run's user; a\n          wiki page is written against the version read, an unversioned file\n          against the hash it replaces, after the server's receipt tool says\n          the user holds `y`, since Fossil passes over what a user may not\n          write and says nothing. Every tool's answer begins with `ok`, and a\n          refusal may give `next_step`, what to do instead. The maintainer,\n          2026-10-15, answering the proposal: \"don't care, just be consistent\";\n          \"our workspace clone is what i'd expect\"; \"make it unique like the\n          runner name\"; \"what does the data show works best?\"; \"yes, include\n          wiki and unversioned files (for binary file sharing). gain parity\n          with trunk agent tools that justify themselves. continue to evaluate\n          against our virtues.\"\n    - HISTORY.md\n      line: 176\n      text: 66. The battery measures the agent tools with local models:\n          battery/main.cr runs saved tasks (battery/tasks: an objective, the\n          checks that score it, the project and wiki pages its scratch server\n          starts with) through Ollama's tool calling, OCX's MCP in the same\n          process, each trial in a scratch project laid out as a run's\n          workspace, scored from the server and never from the model's word,\n          every exact request, tool answer and reply on its record; a call a\n          model writes as text is taken, as a local agent's harness must, and\n          counted. Its results are Fossil tech-notes, one a run, never edited.\n          Its first live trial showed `read`'s text reflowed by the answer's\n          layout, so text of more than one line is now laid out as a block of\n          its lines exactly, and `edit`'s refusal of an empty old on a file\n          that exists now says how to add to it. The maintainer, 2026-10-15:\n          \"can you make a crystal based battery to test the tools with local\n          agents?\", and of where results go: \"instead of putting a battery\n          result on a wiki, can you use a tech-note, since it won't be edited.\"\n    - HISTORY.md\n      line: 177\n      text: 67. A wiki page is changed as a file is, with `wiki_edit`: old,\n          copied exactly from `wiki_read`, replaced by new, old appearing in\n          the page once as it is now, so no one's newer change is lost; old\n          empty adds to the page's end, making it if there is none. It replaces\n          `wiki_write`, a page written whole against its version, which the\n          battery's 7B model never used: it changed pages with `edit` as files\n          (`/wiki/Status`), and once called a `wiki_edit` it had not been\n          offered ([run\n          2](https://ollama.openbeagle.org/ollama/technote/54ff27ae1f)). From\n          the same records, `test` with no name runs every test, as the model\n          gave names of its own (`test_license` for `license`) 110 times;\n          `save` reads a part that runs over lines as one line; and a path that\n          is no file of the checkout points to the wiki's tools. The\n          maintainer's direction for these tools, 2026-10-15: \"gain parity with\n          trunk agent tools that justify themselves. continue to evaluate\n          against our virtues.\"\n    - HISTORY.md\n      line: 180\n      text: 70. A build takes its check-in's files and holds no credential: the\n          workspace step `files` writes the files of the check-in it names,\n          resolved in the node's own repository, into the build's workspace,\n          each executable as the check-in marks it, and leaves no repository,\n          checkout record or password there; a run that never signs in names\n          its user without an account, so `create` makes one only for a run\n          whose workspace takes a `password` step. A build runs the change\n          under test, code no one has vetted, so it must hold nothing that can\n          write to the server: what it produces goes back through its node,\n          under the node's one account. The maintainer, 2026-10-16: \"for this\n          remote agent, that seems like something it can handle itself. it\n          shouldn't need the login of a node on the originator, except for the\n          resulting posts it generates and possibly uv uploads, etc, based on\n          the permissions set on that origination server. so, again, why would\n          i need 2 accounts on my server for that remote instance? why is it\n          even a question?\", and of the plan built from it: \"sure\". A new step\n          kind, as protocol v1, section 15 allows. Found on the way: a node\n          wrote a finished run's kept logs through any link the run left in its\n          workspace (cb9598612c).\n    - HISTORY.md\n      line: 184\n      text: 74. Four tools bring an agent's work to the server, one for each\n          place its files can be, under one rule. `save`: the files are in the\n          run's own checkout, which OCX reaches; it commits and pushes as the\n          run's user (decision 65). `sync`: the files are in the agent's own\n          clone, which OCX cannot reach and which holds no login key; it takes\n          the check-ins as a bundle in the call and pushes them from the run's\n          clone (decision 58, the maintainer: \"just `sync` is the ONLY\n          operation that is required\"). `commit_and_sync`: OCX's MCP runs\n          beside the agent's own clone; it commits there and answers the bundle\n          for `sync`. `commit_and_sync_guide`: the agent has a shell and no OCX\n          of its own; it answers those steps as shell commands (decision 59,\n          the maintainer: \"The local MCP should provide a tool that is aligned\n          with the `ocx.commit_and_sync_guide`\"). The rule they now share\n          (src/ocx/commands/stated.cr): a comment of a title and Intent,\n          Expression and Demonstrates lines, each saying something, a part that\n          runs over lines read as one; never trunk; and, where OCX commits,\n          every change, new files included, once each test the project names\n          has passed since the last edit. `sync` checks a bundle's comments by\n          the same rule, so a comment `save` or `commit_and_sync` writes is one\n          it takes. Before, `commit_and_sync` refused a part of more lines that\n          `save` joined, left out new files that `save` added, and committed\n          with tests unrun, and `sync` checked only that the three lines began.\n          The maintainer's review, 2026-10-16: \"These paths need an explicit\n          keep-or-consolidate decision.\" All four stay. A ChatGPT agent on\n          mechanical-turk reports the guide working and `sync` pushing and\n          pulling (its docs/ocx-mcp-feature-needs-2026-10-15.md), and an\n          agent's own clone and its run's checkout are different places, which\n          a remote call must never take for one another (codex-cloud-2's review\n          in the ocx2 thread, 2026-10-16: \"local preparation and remote\n          publication are complementary operations. Preserve their meanings.\").\n    - HISTORY.md\n      line: 186\n      text: 76. A node is a clone, or the server's own repository, running OCX\n          on its machine, and not a user: the maintainer, 2026-10-16 and 17,\n          \"don't address a clone by its owning user. it makes sense for a clone\n          to have an owner, but the 1:1 thing feels forced.\" Runs still name a\n          node by a login in this pass (a later pass gives runs the clone's own\n          identity), but the words stop equating the two: \"node user\" becomes\n          \"the node's login\", the login OCX on that clone uses, which whoever\n          has the command line there chooses: \"the login chosen by the user\n          with cli access should dictate the greatest capability extended to\n          the OCX application, just like it is for cli usage of fossil\". Asking\n          for a login becomes general, in a group of its own, like Fossil's\n          self-registration, but the user is made only when an admin approves:\n          `register`, on the asker's own machine and its command line alone,\n          makes a random code, keeps it with the login and the capabilities\n          asked in its file of passwords, readable by its owner alone, asks the\n          server at once, so a wrong URL shows on the first call, and prints a\n          link naming the login, the capabilities and the code's SHA-256; every\n          later call prints the same link, from what the file keeps, and\n          refuses other capabilities; once approved, it collects the password.\n          `approve` (was `node_user`), an admin's one press, makes that Fossil\n          user holding exactly the capabilities asked, refusing `a`, `s`, `u`\n          and `v` (which lend what Fossil's reader and developer hold), an\n          empty set and any letter Fossil does not define but `R`; its input is\n          `login` (not `name`, which Fossil takes from a page's query under\n          /ext/ as the page's own path), `key` and `capabilities`, and its\n          `share` switch is dropped, since the capabilities say `y`. It sets\n          again only a user it made that still holds the password it set, so a\n          user deleted and made again by hand under that login is never taken\n          over (a review found `node_user` would). `collect` (was\n          `node_password`) gives the password for the code, needing no\n          capability and changing nothing; `register` sends the code in a\n          POST's body, never in a URL. `node` becomes `poll`, its `--user`\n          `--login`, and until its login is approved it does what `register`\n          does, asking `goi`, and `y` only when given in `--capabilities`; the\n          logic moved from `node` into `register`'s file, not copied. `hook\n          --node USER` becomes `hook --login LOGIN`. `register` needs no\n          capability yet writes its file, so a tool now says whether it may\n          change anything (`changes?`), which only one the web page and MCP\n          withhold may say against its capabilities. The 8-digit fingerprint is\n          dropped: the page says to open only a link the asker itself printed,\n          and then only the asker's code can collect, as long as the hash in\n          the link came from the asker. Kept for compatibility: the config rows\n          `ocx-node-key-LOGIN`, so an approval pressed under the accepted\n          release is still collectable; a file of passwords as `node` wrote it;\n          and the command an installed hook runs, `ocx2-hook --log FILE --node\n          LOGIN %R`, and the watcher's `--node` and `--watch`, so accepting\n          this release breaks no installed hook. Not kept: a node's machine and\n          the server join only on the same side of this change (the earlier\n          release asks for `node_password`, this one for `collect`), so accept\n          on the server first, then on each node's machine, where the timer's\n          `ocx2 node --user` becomes `ocx2 poll --login`, as `hook --node`\n          becomes `hook --login` on the server; a machine still waiting prints\n          the new link with its old code. A code this release keeps carries its\n          capabilities, which the accepted release does not read, until it is\n          collected. The fields of OCX messages, a run's `node` among them, are\n          unchanged. [ARCHITECTURE.md](ARCHITECTURE.md) is rewritten plain: six\n          points and a simpler drawing. New words for the maintainer's\n          approval: the node's login, register, approve, collect, poll, and the\n          group \"Logins\"; on 2026-10-17 the maintainer approved register,\n          approve, collect and poll (\"i like those names\"). The maintainer also\n          said: \"please don't go changing default account permissions\", and\n          that every new term needs their approval ([KEEP.md](KEEP.md)).\n    - HISTORY.md\n      line: 188\n      text: 78. OCX's own agent for local models is one more entry of the one\n          program, as the maintainer's order of 2026-10-14 asks\n          ([PLAN.md](PLAN.md), phase 4): `ocx2 --mcp-ollama URL --model NAME\n          --steps N --system TEXT`, named as a run's command, holds the\n          conversation the battery measured, moved from battery/ into\n          src/ocx/ollama.cr (`Ollama.converse`), so the battery and a run hold\n          one conversation, and what the battery measures is this agent when\n          the run's `--system` is the battery's words and its tools the\n          checkout's group. Its tools are the checkout's group, as MCP serves\n          them to the run's user, answered in the same process (`Mcp.offered`,\n          `Mcp.answer`); a call to any other tool is refused, never run, since\n          MCP would otherwise run any tool the run's user may call (a review\n          found a model could post elsewhere and record a verdict). The model,\n          its system's words and its step budget are the command's arguments,\n          never OCX's code (precept C6, Explicit Arguments, and decision 40);\n          its byte budget is the run's own `process.keep.stdout`, and its only\n          clock the run's `wall`, since a step's read timeout is an argument\n          the battery gives and the agent does not. Each reply is a line of\n          JSON on its standard output, printed before any call it asks for\n          runs, and each tool's answer a line after it, the first request and\n          every reply exactly, so the exchange reaches the record whole, in the\n          run's kept standard output when its process ends, not posted before\n          each step as [PLAN.md](PLAN.md) had it: watching it live is the live\n          status the maintainer described over SSE ([KEEP.md](KEEP.md),\n          2026-10-16), and no session hearing the model's user is woken once a\n          step. So it takes only a run keeping its standard output `always`,\n          since the default keeps it only on failure, and a session only with\n          `deliveries: start`, as it answers one delivery and ends. No request\n          larger than the run keeps is sent, no line past it printed, and no\n          call run without room for its answer, which is cut to fit and ends\n          the conversation, so nothing a call does is missing from the record\n          (a review found a save could land after the reply asking for it no\n          longer fitted). No credential is given to the model, but a test\n          `ocx_test` runs can read the clone's password\n          ([docs/backlog.md](docs/backlog.md)). Once the model calls no tool,\n          its last words are posted as the run's user with `post`, a reply to\n          the delivery's post or a change on its ticket, else where the run is;\n          any other end is said on standard error, and the process exits 1.\n          Delegation (`ocx_delegate`, `ocx2 delegate`) leaves\n          [PLAN.md](PLAN.md) and [USAGE.md](USAGE.md): no file of trunk at\n          a46d73f5bf has it, and an agent sending a model's run conflicts with\n          decision 75, as a run it sends takes no password step, so the model\n          could neither post nor save as its own user; once a pattern such as\n          `run/gemma` is written, a person can hand a subtask off with `create\n          --to POST` in the delegating agent's thread (not yet tried), and an\n          agent doing it itself is in [docs/backlog.md](docs/backlog.md). No\n          protocol piece, message kind, key or glossary term is added; the one\n          new name, `--mcp-ollama`, following `--mcp-http`, is for the\n          maintainer's approval.\n    - HISTORY.md\n      line: 189\n      text: 79. A person is told when a running session was not given their\n          post: when a post or ticket change holding no OCX message, from a\n          user no run names as its node or `process.user`, reaches the thread\n          or ticket of a session running in the node's care and section 9 of\n          protocol v1 gives it to none there, the node replies to it, as its\n          login, `Given to no session:`, naming each such run by the first ten\n          digits of its hash, the first filter that held the post back, by its\n          name in section 9 (`after`, `not its own`, `where`, `heard`), and\n          whom that run hears ([protocol v1, sections 8.2 and\n          9](docs/protocol-v1.md#program)). On cleave, 2026-10-14, the\n          maintainer posted as `ec2-user` to a session whose pattern heard\n          `stone`, and filter 7 dropped each reply without a word: \"I cannot\n          tell if anything is happening after my latest reply\". A session whose\n          process is gone already shows why on the record, by its `ended`, and\n          one not yet begun by having no `started`; a running one holding a\n          post back by a filter said so only in its host's log. The node\n          decides each reply in the same round, under the same lock, from the\n          same running sessions that decide its deliveries, and writes it after\n          every delivery, so it is true under any ordering and a reply that\n          fails holds no delivery back; no session is given a node's reply, and\n          no node replies to a user a run names as its node, so no reply is\n          answered. It adds no key, message kind, tool or refusal, and keeps\n          nothing on the node's host: a plain post, a v1 addition section 15\n          allows, which an older node does not write. A pattern hearing every\n          user and leaving its prompt to choose whom to obey was passed over,\n          since it moves the guard on who may instruct a run into a prompt and\n          covers one pattern; and an opt-in key, since a run leaving it out\n          stays silent, as the wrong pattern on cleave was. Trunk's\n          `src/ocx/unheard.cr`, which [parity-v1.md](docs/parity-v1.md) listed\n          as not copied, needed a list of known agents and a password file; the\n          node already writes as its login. It is step 8 of the order for\n          landing trunk's parity deliverables, as the maintainer directed,\n          built on their words of 2026-10-19: \"please just start developing\n          code again\".\n    - HISTORY.md\n      line: 198\n      text: 88. A `ci` verdict counts only from the node of the run it names,\n          and only on the check-in that run's `started` names\n          ([verdicts](docs/protocol-v1-verdicts.md#reading)); the run's `user`,\n          and a session's `checkins`, no longer make one count. Decision 41 had\n          CI be a session checking each check-in it is given in its own clone\n          and recording `ci` on it as its run's user; that runs the change\n          under test beside the clone that remembers that user's password,\n          which decision 70 forbids for a build, since \"code no one has vetted\n          ... must hold nothing that can write to the server\": a check-in on a\n          watched branch could push passes onto itself or onto any other. CI of\n          a branch is now a pattern, `run/ci`: a session given each check-in on\n          its `checkins`, each starting a process of its own (`deliveries:\n          start`) that sends, with `create` from its clone (decision 81), a\n          build of that check-in by its hash in full from the pattern\n          `run/build`, as a reply to the session; the build's node takes the\n          check-in's files, holds no credential, and writes `ci` on it as its\n          login (decisions 70 and 71), so the session runs no check-in's code.\n          This amends 41, whose session path goes, and 71, whose run-user path\n          goes; no `ci` verdict from a run's user was ever written, as no\n          pattern sent one, so no verdict on the record changes its meaning,\n          and no code changes, since `unaudited` counts `audited` verdicts\n          alone. The pages `run/build`, `run/ci` and `run/bq2-build` (trunk's\n          job: its whole output kept as `job.log`, the ends of its reports and\n          log posted on a failure; it builds `data/sysroot` afresh each run,\n          until a user's cache keeps it, step 9), and `run/claude` with `ends`\n          and a sentence of its prompt saying how to ask for a build, are\n          written for an admin to save, once a release holding `ends` is\n          accepted; [SCENARIOS.md](SCENARIOS.md)'s \"CI on each check-in of a\n          branch\" has its spec run every step past those done by hand. It is\n          step 12 of the order for landing trunk's parity deliverables\n          ([parity-v1.md](docs/parity-v1.md)), built on the maintainer's words\n          of 2026-10-19: \"please just start developing code again\".\n    - HISTORY.md\n      line: 202\n      text: 92. What a tag, a moderator or the order of receipt can change is\n          shown by specs that cross those boundaries. The maintainer passed on,\n          2026-10-20, ChatGPT's review of agent-tools through a91c8e8d8e,\n          verbatim: \"Priority: tags can hide valid lifecycle records.\n          said_tagged_open excludes older started and stop records whenever any\n          tag says ended RUN, before checking that report's sender or content.\n          I reproduced the query in SQLite: tagging an unrelated artifact\n          removed both records from its results. Keep those records until an\n          authenticated ending is established.\"; \"Question ordering needs an\n          adversarial test. QuestionsCommand.asked checks the response's\n          sender, question hash and location, but never checks that the server\n          received the response after the question. A response received earlier\n          could close a subsequently published question. Test that ordering\n          explicitly against the documented state transitions.\"; and \"For\n          weaker reasoning, I'd prioritize tests that cross\n          boundaries—untrusted tags versus authenticated reports, private\n          versus public artifacts, and receipt order versus publication\n          order—over more repeated readings of the same diff.\" The specs found\n          three defects. A tag saying `ended RUN` on an artifact the reader\n          does not read, such as a check-in, hid the run's `started` and its\n          stops from every round and from `status`, since the reader learned\n          which runs were so tagged only from the posts it read: a run with a\n          `started` read as never started, and a stop for it answered it as if\n          it had never started; a tag on a post holding no message, or on\n          another user's `ended`, hid nothing. Now the one query that reads the\n          runs names every run some artifact of any kind is tagged as the ended\n          of, and the reader reads what is about each such run that no `ended`\n          it read ends. The node's own `ended`, held private by Fossil as a\n          post awaiting a moderator, ended the run for the server's node alone,\n          where a node on a clone never holds it: now a message Fossil holds\n          private counts for nothing until it is public, for a node as for a\n          question (decision 90), and a held `ended` is given to no session\n          whose `ends` is true; a session is still given a held post from a\n          user it hears as it arrives, and on the server's node a post approved\n          later reaches no round, both left in\n          [docs/backlog.md](docs/backlog.md). And a response received before\n          its question, the confirmation included, counted, as one written for\n          it in a clone and pushed first would: now a response counts only when\n          the server received it after its question. A moderator's approval\n          keeps the receipt a post arrived by and receives nothing (Fossil\n          2.27, tried 2026-10-21), so what it approves counts as received when\n          it arrived: a response held from before the confirmation and approved\n          after it is one of the closed question's responses, and a\n          confirmation held closes the question as of its receipt once\n          approved, the responses received after it dropping out. Separately,\n          the maintainer, 2026-10-21: \"agents are mistakenly trying to use\n          `sync`, when they should just use a regular `fossil push`.\" An agent\n          in a run's checkout was told only that its check-ins reach the server\n          as it commits, and found `sync` in the list, its summary beginning\n          \"Push your clone's check-ins\"; now `sync`, `commit_and_sync_guide`\n          and `commit_and_sync` begin by saying they are for an agent working\n          outside the OCX server's host that keeps no Fossil password and end\n          by telling one in a run's checkout on the OCX server's host that its\n          commits push as it makes them, and to run `fossil push` if one did\n          not, as [AGENTS.md](AGENTS.md),\n          [docs/remote-agents.md](docs/remote-agents.md) and the patterns\n          `run/claude` and `run/codex`, written for an admin to save, say too.\n          An adversarial review of that change found that it still sent an\n          agent in a run's checkout on a node on another host to `sync`, though\n          that run's clone too is made as its user and remembers the password\n          ([protocol v1, section 5](docs/protocol-v1.md#workspace)): now the\n          summaries of `sync`, `commit_and_sync_guide` and `commit_and_sync`\n          end \"In a run's checkout, on any node? Your commits push as you make\n          them; if one did not, run `fossil push`.\" and begin by saying they\n          are for an agent outside every run's checkout that keeps no Fossil\n          password, the guide's first step and `commit_and_sync`'s next call\n          say \"in a run's checkout, on any node\", and [AGENTS.md](AGENTS.md)\n          and [docs/remote-agents.md](docs/remote-agents.md) say so in their\n          own words.\n    - HISTORY.md\n      line: 220\n      text: 110. A report the node stores on the server's repository whose\n          index or tag then meets a writer outside OCX is written: the node\n          goes on in the order of [protocol v1, section\n          10](docs/protocol-v1.md#reports), kept logs, shares, verdict and\n          `ended`, each written once, and the next post written there indexes\n          it, or leaves it so again while such a writer holds the repository,\n          as a write that meets the writer at an earlier post's index goes on;\n          the node's deliberate check decides nothing until it has indexed\n          each, then tags what lacks its tag ([failure case\n          35](docs/protocol-v1-failures.md#writers)). The node starts no\n          backoffice after an `ended` left so, as decision 87 has it do after\n          each, since its hook would list it before it can be read. A write\n          that stores nothing still fails, and a `started` left so fails its\n          watcher, which launches nothing, since others must see it before its\n          process launches. This amends decisions 95 and 96, under which such a\n          write was a failure of the watcher's own. The live test on the\n          server, 2026-10-23 at 00:32 UTC, release 3869da228e7d: a Codex task,\n          run eabbfe740e in thread 682044729e, changed\n          [docs/backlog.md](docs/backlog.md) as asked and exited 0 in about 20\n          s; the watcher stored its kept logs, post da84f83b4d, but their index\n          failed, \"database is locked\", as a writer outside OCX held the\n          repository, and the watcher ended the run `lost`, ended f58c4d8268,\n          before sharing its patch. Tried on this host, such a writer, an open\n          `BEGIN IMMEDIATE` on the repository, fails Fossil's put and its index\n          each at once, so nothing OCX puts is stored while it holds, and\n          nothing here waits for it to let go\n          ([docs/fossil.md](docs/fossil.md), \"Forum posts\"). The maintainer,\n          2026-10-22: \"Let me know when one click on `accept` is going to give\n          me the functionality I'm seeking\", and \"the contract on this box is\n          as long as the development doesn't disrupt the server, let the agents\n          go a bit nuts.\" A run that did its work and ended `lost` for another\n          program's write gives the maintainer nothing of it, so it ends as it\n          ran, with its share and its `ended`. A close of the temporary\n          checkout a write on the served repository opens fails nothing either\n          when it meets such a writer, as it leaves only Fossil's note of a\n          checkout removed all the same.\n    - HISTORY.md\n      line: 222\n      text: 112. Each write OCX makes on a repository is one Fossil command,\n          which stores all it writes or nothing: a post or a ticket change,\n          with the control artifact tagging it `ocx-message` when it holds a\n          message, written by OCX into a bundle file and stored by `fossil\n          bundle import BUNDLE --publish --force --user USER`, which stores,\n          indexes and tags them together; a control artifact of several tags\n          likewise; a share (`uv add`), a verdict and a single tag (`tag add`),\n          each one command already. A command that meets a writer outside OCX\n          holding the repository, which Fossil fails at once, storing nothing,\n          runs again once Fossil's sql shell has waited for that writer to let\n          go, as SQLite waits on a lock, up to 15 s each time, four runs at\n          most, then fails as before, a failure of the node's own ([failure\n          case 35](docs/protocol-v1-failures.md#writers); [protocol v1, Fossil,\n          section 5](docs/protocol-v1-fossil.md#nodes)). This amends decision\n          110: no report is stored any more without its index and its tag, so\n          none is taken as written while unindexed, Fossil's backoffice follows\n          every `ended` the node writes on the server's repository again, as\n          decision 87 has it, and the deliberate check's mend indexes only what\n          an older release left. The live test on the server, 2026-10-23 at\n          00:32 UTC, release 3869da228e7d: a Codex task, run eabbfe740e in\n          thread 682044729e, exited 0, and its watcher's kept-log post was\n          stored, but its index met \"database is locked\" from a writer outside\n          OCX, and the watcher ended the run `lost` before sharing its patch.\n          Decision 110, of d9dd05e7dd, kept such a report as written and went\n          on; that check-in's review by Gemma held that Fossil's backoffice\n          would list an `ended` left so before it could be read, so none was\n          started after one. An adversarial review of d9dd05e7dd found that\n          this made things worse, each shown by a spec on a scratch repository:\n          a stop after an `ended` left unindexed got a second `ended`, since\n          rounds find runs and endeds by their tags and the next post indexed\n          the leftover but tagged nothing, and a stop written outside OCX got\n          `lost` written again; the hook listed an `ended` while it was\n          unindexed, so no round read it, and Fossil's backoffice runs after\n          any page that answers 200, so starting none did not help; a write\n          that stored nothing, a put, a share, a verdict's tag or a `started`,\n          still ended the run `lost` or left it unanswered, and the user's\n          waiting runs were not handed on; a round whose own tag, reply or\n          answer met the writer raised, so the hook handed no run; and a\n          control artifact of tags left unindexed was never indexed. It\n          proposed the one command, which it tried, and this change tried again\n          with the wait ([docs/fossil.md](docs/fossil.md), \"Forum posts\"):\n          `fossil bundle append` names artifacts by SHA1 whatever the hash\n          policy, so OCX writes the bundle itself, naming each as `fossil\n          hash-policy` says; `fossil test-xfer`, the server's sync handler,\n          whose transaction would wait on the lock itself, crashed. The\n          maintainer, 2026-10-22: \"Let me know when one click on `accept` is\n          going to give me the functionality I'm seeking\", and \"the contract on\n          this box is as long as the development doesn't disrupt the server,\n          let the agents go a bit nuts\"; and, 2026-10-18: \"please don't go down\n          any path with a possible race condition\". Nothing here depends on\n          timing: a write goes through whole or stores nothing, and what it\n          waits for is the writer's lock, never a time, so only how long it\n          takes depends on that writer. A ticket change's text reaches Fossil\n          in a file now, not as one argument, so a kept log over 128 KiB on a\n          ticket run is posted too; and the temporary checkout a post on a\n          repository named outright needed is gone with the two commands that\n          needed it. This change's own review by Gemma (gemma4:31b), four\n          rounds, held no finding; two misreads, that the wait fails at once\n          under the writer and that the check's mend runs outside it, made the\n          code's comments say why SQLite waits on `BEGIN IMMEDIATE` and that\n          every command runs through it.\n    - KEEP.md\n      line: 84\n      text: test records so that they don't clutter the workspace. ... I agree\n          they are\n    - KEEP.md\n      line: 101\n      text: adding any features without a use case. oh, testing is a valid use\n          case,\n    - KEEP.md\n      line: 113\n      text: create to write the message), the testing for the precepts, the\n          release\n    - KEEP.md\n      line: 145\n      text: access should dictate the greatest capability extended to the OCX\n    - PLAN.md\n      line: 30\n      text: Each precept is a testable consequence of a README axiom and\n          virtue. The\n    - PLAN.md\n      line: 151\n      text: test has passed. The battery holds the same conversation, so what\n          it measures\n    - PLAN.md\n      line: 158\n      text: Parsimony means the shortest *sufficient* prompt, measured by the\n          task; its\n    - PLAN.md\n      line: 172\n      text: | `ocx_context` | The run, its objective, its working branch, its\n          unsaved files and its tests. |\n    - PLAN.md\n      line: 175\n      text: | `ocx_test` | The project's tests, named in its checkout, their\n          output bounded. |\n    - PLAN.md\n      line: 176\n      text: | `ocx_save` | A check-in on the run's own `agent/` branch, once\n          each test has passed; never a merge or a verdict. |\n    - PLAN.md\n      line: 258\n      text: - **Parsimony admission.** State the minimal contract and fixed\n          work budget for each slice. A new tool, state file, abstraction or\n          model step earns its place by a demonstrated need in that slice: a\n          scenario's step, or a test that demonstrates a tool. What loses its\n          use is removed, not guarded (the maintainer, 2026-10-08). A Gemma\n          failure prompts inspection of the task and interface before\n          increasing model size or adding machinery.\n    - PLAN.md\n      line: 263\n      text: - **Exchanges on the record.** Every exact model request,\n          advertised tool schema, raw response and tool result belongs where\n          the run is, whole, in the run's kept standard output, when its\n          process ends; no credential is given to the model, though a test\n          `ocx_test` runs can still read the clone's password\n          ([docs/backlog.md](docs/backlog.md)). From the record's view, a\n          person and an agent differ only by user.\n    - PLAN.md\n      line: 264\n      text: - **One place for each topic.**\n          [knowledge-map.json](knowledge-map.json) says which document holds\n          what; a topic is written there and linked from anywhere else, and a\n          test record is a Fossil tech-note. Neither a green spec nor an old\n          decision silently changes a document.\n    - PLAN.md\n      line: 276\n      text: - **Objective test:** the README states what OCX is for, but not\n          yet a\n    - PLAN.md\n      line: 278\n      text: tests substitution; a task that also produces a reviewed change\n          tests\n    - README.md\n      line: 7\n      text: [`ocx-rootfs/`](ocx-rootfs/README.md) builds, starts and tests the\n          public server and the client from a BQ2 seed.\n    - README.md\n      line: 50\n      text: derives testable precepts from them and records implementation\n          progress.\n    - README.md\n      line: 148\n      text: It records what these functions still lack and how each gap will be\n          tested\n    - ROADMAP.md\n      line: 19\n      text: invariants. `fossil` remains a testing tool and fallback component.\n    - SCENARIOS.md\n      line: 79\n      text: editing, testing, saving, requesting a credential-free build, and\n          receiving\n    - SCENARIOS.md\n      line: 91\n      text: | 3. Its change | `ocx_edit`, `ocx_test` and `ocx_save` over its\n          run's MCP: a check-in on its `agent/` branch, once each test has\n          passed, received from its user | works: decisions 65 to 67; an agent\n          reached through a tunnel has them once its run is of a release that\n          holds them |\n    - SCENARIOS.md\n      line: 100\n      text: which tested each new check-in on a branch and tagged it `ci` green\n          or red:\n    - USAGE.md\n      line: 64\n      text: | Test and save a run's checkout | ☑ | not offered: the web page is\n          not a checkout | `ocx2 test [--name NAME]`, `ocx2 save TITLE INTENT\n          EXPRESSION DEMONSTRATES` | `ocx_test`, `ocx_save` |\n    - battery/audits/seeded.json\n      line: 81\n      text: \"id\": \"untested-clean\",\n    - battery/audits/seeded.json\n      line: 82\n      text: \"pair\": \"untested\",\n    - battery/audits/seeded.json\n      line: 86\n      text: \"no test\",\n    - battery/audits/seeded.json\n      line: 88\n      text: \"not tested\",\n    - battery/audits/seeded.json\n      line: 89\n      text: \"untested\",\n    - battery/audits/seeded.json\n      line: 90\n      text: \"without a test\",\n    - battery/audits/seeded.json\n      line: 91\n      text: \"without test\",\n    - battery/audits/seeded.json\n      line: 92\n      text: \"lacks a test\",\n    - battery/audits/seeded.json\n      line: 93\n      text: \"missing test\",\n  more: 266\ntook_ms: 144.8\nlog:\n  - find_text\n    changes: false\n    text: test\n    under: .\n","refused":false}
{"received":"{\"model\":\"gemma4:31b\",\"created_at\":\"2026-11-09T05:50:59.831512387Z\",\"message\":{\"role\":\"assistant\",\"content\":\"\",\"thinking\":\"The `ocx_test` tool failed because the project names no tests. It mentioned `ocx-tests.json`, but that file doesn't exist.\\nThe prompt says \\\"Run the tests, then save\\\". If there are no tests, then `ocx_test` might just return this \\\"no tests\\\" message.\\nHowever, I should check if there is any other way tests are defined. `ocx_test` says: \\\"the project names its tests in ocx-tests.json\\\".\\n\\nLet me check if I can find any other test-related files or if I should just proceed to save since there are no tests to run.\\nWait, if `ocx_test` returns `ok: false` it might be an issue. But it says `stopped: the project names no tests`.\\n\\nLooking at the project structure from the `find` results, there aren't any obviously named test files except for things like `spec/guards/...` which seem to be Crystal specs.\\nWait, the `ocx_test` tool is for the project's tests. If `ocx-tests.json` is missing, maybe the project currently has no tests that `ocx_test` can run.\\n\\nLet me try to run `ocx_test` again and see if it's really a failure or just a \\\"no tests\\\" state.\\nThe output was:\\n```\\nok: false\\ntool: test\\ndry_run: false\\nstopped: the project names no tests\\nnext_step: the project names its tests in ocx-tests.json\\n```\\nThis seems to indicate that `ocx_test` requires `ocx-tests.json` to know what to run.\\n\\nIf there are no tests, I cannot \\\"run the tests\\\" in the way the tool expects.\\nBut the instructions say \\\"Run the tests, then save\\\".\\nMaybe I should check if there are any other files that define tests.\\nI saw `spec/guards/size_spec.cr` and others in `PLAN.md`.\\nBut `ocx_test` specifically looks for `ocx-tests.json`.\\n\\nLet's double check if `ocx-tests.json` might be in another directory? `ocx_find` didn't find it.\\n\\nWait, I'm an agent. If the tools say there are no tests, and I've done the edit, maybe I can just save?\\nBut usually, \\\"Run the tests\\\" is a requirement.\\nIf I can't find tests, maybe I should look for how to run them manually or if they are indeed missing.\\nActually, the `ocx_test` tool's documentation says: \\\"Run the project's tests in the checkout as it is now, all, or one by the name the context tool lists\\\".\\n\\nIf `ocx_context` doesn't list any tests (it said `tests: none`), then there are no tests to run.\\n\\nLet me check `ocx_context` again.\\n`result: ... tests: none`\\n\\nSo there are no tests. I will proceed to save.\\n\\nWait, the prompt says: \\\"Run the tests, then save, with a comment that is a title line, then paragraphs beginning Intent:, Expression: and Demonstrates:.\\\"\\n\\nSince there are no tests to run, I have \\\"run\\\" them (and they \\\"passed\\\" in the sense that there are none).\\n\\nOne more thing: I should make sure I replaced the exact sentence.\\nOld: `Still to show: the pattern `run/gemma` on the server and its first proof.`\\nNew: `The pattern [`run/gemma`](https://ollama.openbeagle.org/ollama/wiki?name=run/gemma) is on the server; its first proof is still to show.`\\n\\nLet's check my `ocx_edit` call.\\n`old`: `| 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](https://ollama.openbeagle.org/ollama/technote/7c2332a567)). Still to show: the pattern `run/gemma` on the server and its first proof. |`\\n`new`: `| 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](https://ollama.openbeagle.org/ollama/technote/7c2332a567)). The pattern [`run/gemma`](https://ollama.openbeagle.org/ollama/wiki?name=run/gemma) is on the server; its first proof is still to show. |`\\n\\nThis looks correct.\\n\\nNow I will save.\",\"tool_calls\":[{\"id\":\"call_twnwtd8a\",\"function\":{\"index\":0,\"name\":\"ocx_save\",\"arguments\":{\"demonstrates\":\"The table row for \\\"Local models: the native agent\\\" in PLAN.md now contains the updated sentence with a link to the run/gemma wiki page.\",\"expression\":\"Updated a sentence in PLAN.md in the \\\"Local models: the native agent\\\" table row.\",\"intent\":\"Update the status of the run/gemma pattern in PLAN.md to reflect that it is on the server.\",\"title\":\"Update run/gemma status in PLAN.md\"}}}]},\"done\":true,\"done_reason\":\"stop\",\"total_duration\":54043688000,\"load_duration\":239229942,\"prompt_eval_count\":21915,\"prompt_eval_duration\":6440455641,\"eval_count\":1281,\"eval_duration\":46393229993}"}
{"name":"ocx_save","arguments":{"demonstrates":"The table row for \"Local models: the native agent\" in PLAN.md now contains the updated sentence with a link to the run/gemma wiki page.","expression":"Updated a sentence in PLAN.md in the \"Local models: the native agent\" table row.","intent":"Update the status of the run/gemma pattern in PLAN.md to reflect that it is on the server.","title":"Update run/gemma status in PLAN.md"},"text":"ok: true\ntool: save\ndry_run: false\nresult:\n  branch: agent/run-66700aad-661eee85\n  checkin: aebacd25dc93981f2ac1248466cc871a5e249e8e18b372bebc9c52f28ef15053\n  landed:\n    - aebacd25dc93981f2ac1248466cc871a5e249e8e18b372bebc9c52f28ef15053\n      link: https://ollama.openbeagle.org/ollama/info/aebacd25dc93981f2ac1248466cc871a5e249e8e18b372bebc9c52f28ef15053\n      sender: run-66700aad\ntook_ms: 506.7\nlog:\n  - read_save_state\n    changes: false\n  - commit_work\n    changes: true\n    branch: agent/run-66700aad-661eee85\n    message:\n```\nUpdate run/gemma status in PLAN.md\nIntent: Update the status of the run/gemma pattern in PLAN.md to reflect that it is on the server.\nExpression: Updated a sentence in PLAN.md in the \"Local models: the native agent\" table row.\nDemonstrates: The table row for \"Local models: the native agent\" in PLAN.md now contains the updated sentence with a link to the run/gemma wiki page.\n```\n  - push_work\n    changes: true\n  - confirm_landed\n    changes: false\n    pushed: aebacd25dc93981f2ac1248466cc871a5e249e8e18b372bebc9c52f28ef15053\n","refused":false}
{"received":"{\"model\":\"gemma4:31b\",\"created_at\":\"2026-11-09T05:51:06.496360353Z\",\"message\":{\"role\":\"assistant\",\"content\":\"The sentence in `PLAN.md` has been updated as requested. I ran the tests (which returned no tests defined for the project) and then saved the change with the required comment format.\\n\\nUpdate run/gemma status in PLAN.md\\nIntent: Update the status of the run/gemma pattern in PLAN.md to reflect that it is on the server.\\nExpression: Updated a sentence in PLAN.md in the \\\"Local models: the native agent\\\" table row.\\nDemonstrates: The table row for \\\"Local models: the native agent\\\" in PLAN.md now contains the updated sentence with a link to the run/gemma wiki page.\"},\"done\":true,\"done_reason\":\"stop\",\"total_duration\":6151147891,\"load_duration\":246280849,\"prompt_eval_count\":22540,\"prompt_eval_duration\":486371373,\"eval_count\":141,\"eval_duration\":5135719875}"}