nc://qa

v0.1.0Ships with Nodecode
Backnodecode-ai
pomterretools/nodecode-guard: a README -- the operator (2026-10-10), after Telegram's: "also for guard". Its page on nodecode.ai/cells had no About text. One file: what guard does and that it is a speed bump, not a boundary; turning it on (/setup's Recommended, `nodecode add guard`) and off (space in /cells, "enabled": false); the nine built-in rules as a table with an example each; how a call is read (the built-ins fire only when the same eval call starts a process, so a file that mentions sudo is still writable, and a call that both spawns and carries a risky command is refused); the refusal text the agent reads; the guard section's deny (id, pattern, reason, gated, ungated by default) and allow (exempts only what it covers), with an example; the keys; the tests. Every claim read off cell.lisp, the kernel's waist/textrules.lisp and the cell's tests at this commit; the header comment's "cells": ["nodecode-guard"] is no longer how a cell turns on, so the README does not repeat it.88bf4c7· 10 Oct1 commit
test3 filescell.lisp15.7 KBpage.lisp13.9 KBreport.schema.json4.1 KB

nodecode-qa

One page of counts a week, only if you say so. The whole page is report.schema.json beside this file; /qa show prints the next one exactly as it would go.

What leaves

Once a week, when qa.share is weekly, one JSON page:

  • the build and the platform (0.0.1+abc123, x86_64-linux)
  • per provider and model: rounds, retries, failovers, tokens to the nearest thousand, the median time to first token
  • turns completed, cancelled, failed by condition class
  • per tool: calls, results that began with ERROR:, the median duration
  • what the model reported through report_issue, by tool and symptom
  • process-ending crashes by condition class

What never leaves

No prompt, no answer, no path, no file, no hostname, no session id, and no id that follows the install. A page carries a nonce minted for that page; the collector keeps it two weeks to drop a redelivery and forgets it. Two pages from one box cannot be tied together, by us or by anyone.

The counting starts when sharing is chosen, never before: the first page covers the week after the choice.

The model's notes

report_issue is a tool the model calls when another tool misbehaved: a tool name, a symptom, one sentence. The note is kept on this machine, /qa notes lists it, and the weekly page carries only its tool and symptom as a count. The text leaves one way: /qa push, by hand, after reading what /qa notes shows. A call to (qa:push-notes) from a turn is refused.

The switch

The setup wizard asks once, as one panel with two options; /setup asks again; (config-set '("qa") '(:share "never")) answers it in a conversation. "enabled": false vetoes the cell, tool and all. NODECODE_QA=0 in the environment turns sending off whatever the config says, push included.

The answer is read when the cell starts. The wizard installs the folder, asks, then starts it, so a first run reads the answer; a folder that was already running when /setup asked keeps what it read at boot until (restart-cells "nodecode-qa") or the next launch, and /qa says which it is.

/qa          one line: sharing or not, when the next page is due, notes kept
/qa show     the next page, as it would go
/qa send     send it now
/qa notes    the model's notes, newest first
/qa push     ship the notes' text, by hand
/qa clear    drop the notes

How it works

The engine already journals every provider round, retry, failover, tool result and turn end into history.db. The page is a fold over those facts after a cursor, computed at the send; nothing is queued. One state row holds the cursor (qa/cursor: log position, window start, last send, the nonce while a send is open, the stdio log offset), one the notes (qa/notes, 200 newest). A refused page keeps its nonce and is folded again from the same cursor an hour later; on 2xx the cursor moves past it.

The collector

POST {url}/api/qa with the page as the body, content-type: application/json, the organism's user agent. Any 2xx is accepted; anything else is retried under the same nonce. The collector upserts on the nonce and keeps it fourteen days. POST {url}/api/qa/notes takes a by-hand push: {"report": "nodecode/notes/1", "version", "platform", "notes": [{"tool", "symptom", "note", "provider"?, "model"?}]}. url defaults to the release host (update.url's host) and is qa.url in the config.

The collector itself lives in the marketplace repo (nodecode-marketplace): the two routes under web/src/app/api/qa/, the contract read strictly in web/src/lib/qa.ts, the tables in db/migrations/0029_telemetry.sql (they kept the cell's first name) and the desk board at /admin/qa.

Tests

just qa-test — the page is counts only and carries no text from any fact; a refused page keeps its nonce and cursor and the retry resends the same page; the first look begins at the consent moment and sends nothing; never, unanswered and the environment switch ship nothing; the tool keeps a bounded note and never fails; notes leave only by hand; the page's keys are the schema's.

Add nc://qa

  1. 1

    Install Nodecode

    Once per machine.

    $ curl -fsSL https://nodecode.ai/install.sh | sh
  2. 2

    Add the cell

    It ships with Nodecode, pinned at 88bf4c7; this turns it on.

    $ nodecode add nc://qa

    Or tell the agent add the qa cell.