Skip to main content

Shipped this week: 3 PRs in OpenCastor + a redesigned robotmd.dev

9 min read By Craig Merry
opencastor robot-md release weekly robotmd.dev RCAN compliance

This was a heavy shipping week. Three PRs in OpenCastor, a major robot-md release, four more PRs to rebuild robotmd.dev from scratch, and a parser bug squashed by bob during his v1.4.0 smoke test. Here’s what’s in main and what isn’t.

OpenCastor #867 — the silent-failure stack, closed

OpenCastor had accumulated three distinct failure modes that all shared a common shape: something went wrong, nothing surfaced, the operator didn’t know. The full fix took three PRs.

PR #879 (merged bb8412b) — Bug A: error swallowing at the provider edge. The claude_proxy was catching exceptions, logging them internally, and returning a 200 response with an error body instead of a 5xx. A caller that didn’t inspect the response body couldn’t tell the difference between a successful completion and a silently failed one. The fix was straightforward: let the exception propagate, return a 503.

PR #880 (merged 466a010) — Bug B: consent scope threshold to HiTL gate auto-registration. When consent.scope_threshold was set in the manifest, it wasn’t being automatically wired to a HiTLGate — the operator had to do that manually, which no operator was doing, so high-scope actions were passing without triggering a gate. The fix auto-registers the HiTLGate from the consent config at runtime. Two-step PENDING_AUTH semantics (RCAN §8) were also added here: an action that hits a gate returns PENDING_AUTH with an auth reference, and the requester polls until the operator approves or denies. Before this, the gate could just block silently.

PR #881 (merged 87b55b7) — notify wiring. HiTLGate.notify and authority._notify_owner had been stubs — they existed in the code, they were called, and they did nothing. The cross-cutting fix wired both through a NotifyDispatcher that fans out to configured channels: WhatsApp, Telegram, Discord. A HiTL gate firing on bob now sends a notification to wherever I’ve configured it to go.

Together these three PRs close issue #867. The practical effect is that when a capability invocation fails, I hear about it; when a gate fires, I hear about it; and the RCAN §8 PENDING_AUTH flow works as specified rather than as a stub.

robot-md v1.4.0

The details are in the v1.4.0 release post; I’ll summarize the three tracks here.

SP-HP (hot-plug daemon) — a new robot-md hotplug-daemon process that watches the OS device-event stream (pyudev on Linux, ioreg + pyserial on macOS, polling on Windows) and appends a hash-chained event log at ~/.robot-md/hotplug-events.jsonl. HIGH-confidence events (VID:PID matches a single known preset, one backend installed) auto-bind to ROBOT.md. The key queue contract: first writer wins, AlreadyResolvedError on any subsequent resolution attempt. Twenty-four tasks, all behind tests. The systemd / launchd service installer is included.

SP-AN (announce + confirm) — an MCP resource at robot-md://hotplug/pending that fires notifications/resources/updated when the queue changes. Claude’s skill text describes what to do when the notification arrives: announce a HIGH-tier auto-bind by voice, give the operator 30 seconds to say “undo,” call hotplug_confirm({event_id}, "reject") if they do. If the event was already confirmed via a different channel (terminal, future pendant), Claude gets already_resolved back and acknowledges instead of looping. The end-to-end demo bob is going to run when the hardware smoke clears: replug the SO-ARM101, hear Claude announce the bind within ~5 seconds, say “looks good.”

SP6 Phase 1 (self-attested spatial scores) — the verifier and signer in spatial_eval are now real: spatial_eval_verify loads the keystore keypair and checks the ML-DSA signature; spatial_eval_run_execute stamps a base64 ML-DSA signature before writing Score.json. Two bugs that the original Phase 0 stubs were masking got fixed in the process: the canonical bytes for signing now clear the rcan_signature field before serializing (you can’t sign over your own signature), and run_full_tool’s merged score gets re-signed after the probe + execute tracks are combined, so what’s on disk and what’s returned are byte-identical.

163 tests across the three tracks, green on Linux. Bob smoke runs are next.

SP6 Phase 1.5 — RRF counter-sign

Three more PRs (robot-md #29, #30, #31) and one on the RRF side (#73) extend the SP6 work toward registry-attested scores:

  • spatial_eval_submit_to_rrf is now wired as an MCP tool; it packages the Score.json and posts to the §27 endpoint.
  • RRF #73 (“§27 spatial-eval submission + counter-sign endpoints”) landed both halves at once: the POST /v2/robots/<rrn>/spatial-eval receiver, and the counter-signing logic that takes the robot’s self-attested score, re-runs the held-out probe split independently, and appends RRF’s own ML-DSA counter-signature if the score is within tolerance.

What this unlocks (and what already shipped): the §27 endpoints are live (Cloudflare deploy succeeded today), and bob has already completed the first end-to-end submission — submission ID sub_8c686d6e-6e87-49ef-8bb5-0b51e5982de7. verify_tool against the resulting counter-signed score returns {"ok": true, "attestation": "registry-attested"}. Two follow-up PRs (#75 / #76) were needed to clean up a secret-encoding mishap discovered along the way; the keypair has been rotated and the chain is clean. The leaderboard distinction is real now: only registry-attested scores show up on the public spatial-eval leaderboard at RRF.

robotmd.dev — complete redesign

The old robotmd.dev was a landing page and a spec. It couldn’t answer the questions I was getting: “What agents does robot-md support?”, “How do I install it on Gemini?”, “Where’s the MCP docs?”, “What does compliance status check?” Four PRs landed in the robot-md repo (the site lives under site/ alongside the CLI) across four days to fix this.

robot-md #33 — IA review, landing-page draft, managed-agents stub, working waitlist. The IA review was the hard part: mapping out what questions different audiences (hobbyists, roboticists, compliance engineers, agent-surface maintainers) were actually asking, and which page should answer each one. The waitlist is backed by a Cloudflare Workers KV endpoint — submit your email, it goes into KV, I can query it from the Workers dashboard.

robot-md #34 — eight MVP secondary pages: /spec/, /mcp/, /registry/, /compliance/, and four agent pages (/agents/claude-code/, /agents/gemini/, /agents/codex/, /agents/chatgpt/). CSS was extracted out of inline styles into a shared stylesheet. Each page follows the same template: “what this surface is, how to install it, what you can do with it, what doesn’t work.”

robot-md #35render-spec.py, a Python script that converts the RCAN spec Markdown into HTML for /spec/; the /agents/ hub page that links to all five agent surfaces; and /agents/q/ (Amazon Q surface — documenting the aarch64 block and what to expect when it’s resolved).

robot-md #36 — a parser fix for compliance status . when passed a directory argument instead of a file path. Closes issue #32. I’ll say more about this below.

What’s live now: 14 routes (/, /spec/, /agents/ hub, four /agents/<surface>/ pages plus the new /agents/q/, /mcp/, /registry/, /compliance/, /managed-agents/, /robots/, /status), a working waitlist endpoint, build-time stats injection (so numbers like the npm-weekly download count and the live RRF endpoint count are pulled at deploy time, not hardcoded), a strict Content Security Policy. Net new across the four PRs: ~+8,750 lines (robot-md #33 +2,946, #34 +3,914, #35 +1,829, #36 +67).

One small bug fix — issue #32

Bob surfaced this during the v1.4.0 smoke test. robot-md compliance status . — passing a directory argument, which is the natural thing to type from inside the robot’s repo — was failing with a confusing error because the parser was trying to open the directory path as a file.

The fix is five lines at the parser layer: if the path is a directory, append ROBOT.md and try again. Every CLI command that calls parse_file benefits from the fix, not just compliance status.

It took two CI loops to close — the first fix passed the logic tests but the ruff linter rejected the formatting, so a second commit cleaned that up. Minor, but it’s the kind of thing that has to be clean before it ships.

What didn’t ship (deliberately)

  • Bob’s manual notify-wiring smoke. The NotifyDispatcher gateway path is dormant on the current RPi setup — I need to configure the actual notification tokens and verify the channel routing end-to-end against hardware. That’s a manual checklist item, not code.

  • /docs/ on robotmd.dev. Deferred to issue #21. The four-PR IA sprint built the structure; /docs/ needs actual tutorial content, which is a separate writing project.

  • /robots/bob/ case study. Gated on completing the hardware re-verification after the v1.4.0 smoke. Once bob runs the SP-AN demo end-to-end (replug → announce → confirm), that becomes the canonical case study.

  • A patch-only v1.4.1. The issue #32 fix didn’t get bundled as a tiny patch — by the time I cut the next tag, SP-AN v2 (#28), SP6 Phase 1.5 (#29–#31), SP3 Phase D (#27), and the four-PR robotmd.dev redesign (#33–#35) were also on main. That’s not a patch by strict semver, so the actual cut went out as v1.5.0 — a MINOR bump that bundles the parser fix with the four feature tracks. Tag 60b8bbe on RobotRegistryFoundation/robot-md, PyPI publish workflow triggered.

What next week looks like

RRF §27 is now live (PR #73 merged today, Cloudflare deploy succeeded), so SP6 Phase 1.5 is effectively closed and robots can get registry-attested spatial-eval scores. Bob’s first end-to-end registry-attested submission is the next concrete milestone.

After that: bob’s SP-AN smoke run (replug → announce → confirm → manifest reflects it), and potentially a v1.5.1 patch if the smoke surfaces anything worth fixing. If Managed Agents beta access lands, the Compliance-bot work moves to the top of the queue — the design is written, the primitives are in place, the missing piece is the hosted runtime.

The ecosystem overview from two days ago is still the right starting point if any of this is new to you. The v1.4.0 post has the deep technical dive on hot-plug and SP6. And robotmd.dev is the live reference for all of the above.