Changelog

What's new in OpenCastor — features, fixes, and breaking changes.

3.4.0 Latest Paint a picture iOS 1.3 September 10, 2026

Ask the robot to paint a picture, from the phone

  • A paint job on the console — POST /eval/paint starts one castor bench sacpaint run on the robot from the operator’s paint.json profile; GET /eval/paint reports strokes, misses, model calls and finally the score; POST /eval/paint/stop ends it. One job at a time: the arm is one arm, and every stroke still goes through the gateway with a signed receipt.
  • A picture of your own — POST /eval/picture takes a JPEG and traces its edges into a scoring skeleton (castor bench sacpaint new --auto-trace), so the paint is still scored.
  • Watch it grow — the OpenCastor body posts its canvas to the console after every move (-E canvas_post_url) and writes a small progress file (-E progress_path).
  • iOS 1.3 (build 78, TestFlight) — a Paint a picture card on every paired robot’s page: the photograph of Sacramento by default, a photo picker, one button, the live canvas, and a plain-language reading of the score.
  • Measured — Opus through the owner’s subscription painted Sacramento on an SO-ARM101’s virtual easel in 31 minutes, 52 looks, 147 moves, composite 0.35; the oracle trace scores 0.82 on the same rig.
3.3.0 castor bench PaintBench September 10, 2026

Sacramento PaintBench is a castor bench benchmark

  • castor bench sacpaint — the standalone sacpaint package moves into the runtime as castor.bench.sacpaint. A robot with a pen must reproduce a photograph of Sacramento from camera feedback; any photo of the finished sheet scores offline with castor bench sacpaint score PHOTO. Install the eval stack with pip install "opencastor[paintbench]"; a plain install pulls no eval framework.
  • The reference is the photograph — the model sees the original picture; the scorers read a stroke skeleton traced over its landmarks, and every EvalLog carries both hashes.
  • Media as categories — every score carries medium (pen, virtual, sim), each ranked on its own. -E medium=virtual -E calibration=easel runs an arm with no paper and no pen: the canvas is inked from where the arm measured its tip. First real-arm run, an SO-ARM101 on 2026-09-09: 649 moves, 62 minutes, composite 0.82.
  • The runtime’s first Python gateway client — RCAN envelopes to /v1/invoke with signed receipts kept as JSONL, a deny raised as a safety abort with the driver’s sub-code, a reach that ran but missed told apart from a fault.
  • Console — /eval/reference.png serves the packaged photograph; the 3.2.0 /eval/* routes for the phone’s frames and corners are now in the changelog too.
3.2.0 Microduck castor bench September 8, 2026

The Microduck is the reference robot, and the ten-minute goal is a command

  • castor bench ten-minutes --robot microduck — seven timestamped checkpoints from “package installed” to “robot.stop observed after silence, naming which deadman fired”, a JSON record with versions, shas, duck identity and every wire line, an EvalLog export that inspect-robots reads back byte for byte, and three targets: a mock robotd, Pollen’s own simulator running the real robotd, and a real duck. Today the sim passes C1 to C6 in 3.5 seconds; nothing has touched a physical duck yet, and the record says so.
  • Five wire faults fixed — castor duck had never been run against a real robotd. Four keys read from the wrong struct, and robot.subscribe had never once succeeded. Two independent runs against the live daemon found the same fifth fault.
  • castor up --archetype microduck — six units including the bridge as duckbridge.service, one token the phone and OpenCastor share, port 7788 agreed in four places.
  • transport: webrtc — drive a duck over mediad’s own network transport with no SSH key, no robot group and no reboot (pip install "opencastor[microduck-webrtc]"). The guide now states plainly that mediad is unauthenticated on 0.0.0.0.
  • castor doctor knows ducks and calls a mock driver a failure; the duck’s LLM tools finally register; castor duck writes a manifest castor run accepts, never prints “Duck ready.” for a duck that did not answer, and says its speed envelope out loud.
  • RC car — castor doctor reads the PCA9685 back and reports a chip that forgets its configuration, found on the first hardware contact; the bring-up checklist gained that step.
3.1.0 Microduck castor up September 8, 2026

Box to driving in under ten minutes, and the Microduck

Published on PyPI as 1!3.1.0: install with pip install "opencastor>=3.1". The epoch is what makes pip prefer this line over ninety-seven older date-versioned releases that had no castor up in them.

  • Real wheels are one question away — castor up asks, with the wheels-off-the-ground warning, when it detects a PCA9685; rc-car-actuator is a core dependency; the template’s channels match every reference vehicle; the manifest can no longer draft a stop (duration_s has no default).
  • Discovery ships — a fifth unit advertises _opencastor._tcp with rrn, ports, name and manifest path; castor discovery check proves it from the wire.
  • castor doctor reads the robot it provisioned — real ports, /dev/i2c-1, simulated wheels, mDNS, USB current versus a streaming camera, every capability gap, each with a pasteable fix and a non-zero exit when the car cannot move.
  • The Pi image enables I2C at first boot and ships as one file; the install and port docs agree with the code; castor init asks the robot’s shape first.

The Microduck, and one command from bare host to paired robot

  • Pollen Microduck support — a 25 cm walking biped whose motion comes from RL policies executed by its own robotd daemon at 50 Hz. OpenCastor is an intent client over robotd's JSON-RPC 2.0 NDJSON socket; robotd keeps exclusive ownership of the motor bus. Hardware guide →
  • castor duck — one command from a duck on the desk to a duck under an LLM: find it, prove we can reach it, ask robotd how it feels, write the config. Discovery tries five things (local socket, hostnames, duckctl ip over Bluetooth, mDNS, ARP with --deep) because Pollen's own docs admit mDNS “resolves when it feels like it”. The two things that can block you — SSH access and robot group membership — each get their exact fix printed.
  • The whole vocabulary — reading duck-ipc-proto turned up twenty-two robot.* methods against the eleven the driver knew. robot.do now carries the five scripted skills (ground_pick, both kicks, sit_toggle, roulade); robot.sound carries the seven-sound voice bank including the held wheee; robot.mouth and robot.pose join the twist as continuous intents.
  • Choreography — robot.do runs exactly one skill, so there is no way to say “walk to the ball, line up, knock it toward the couch, then celebrate”. Every verb exists; the sentence does not. Thirteen primitives now carry how long a move occupies the duck and whether it holds the robot exclusively, and thirteen routines compose them — fetch, greet, patrol, nudge, celebrate, settle. castor duck do "greet me, then patrol the room".
  • castor up — the ten-minute contract as a command: detect hardware → pick archetype → generate the robot home (signed ROBOT.md, rcan.yaml, bearers, policy, keys, runtime) → start the systemd units → detect a brain → write the pairing QR. Non-interactive and idempotent throughout: every question it could ask is one it can answer by looking at the machine.
  • Universal-link pairing — the QR is a link any camera understands, with the server half to match. The QR states what this robot can do, so a car stops arriving as an arm.
  • DuckKit — the duck's brain as a zero-dependency Swift package, so a phone runs the real trained policy with no robot in the room. github.com/craigm26/duckkit
  • Fixed — rc-car-actuator was a hard requirement that broke pip install opencastor for weeks; it is now the [rc-car] extra. The peripheral scanner could not see a board that had just been plugged in. Two tools shared one file and disagreed about its shape, and --force ate a live key.

A plan is a proposal. The choreographer computes no permission — every motion goes out through the driver and the SafetyLayer, the duck's own limits apply on top and come back in robot.state.limited_by, and steps abort on a fall or a flat battery. robotd remains the only thing that decides what a servo does.

3.0.3 July 31, 2026

Auto-detection must never offer a LoRa radio as a servo bus

  • Detection put a green tick next to /dev/ttyACM0 — an ESP32 LoRa radio — labelled “controller board”, and castor arm verify therefore defaulted to it. A denylist is now checked before any allowlist match: Espressif/Adafruit/Arduino VIDs plus product-string matches on heltec|lora|meshtastic|meshcore|esp32|rak|t-beam.
  • The ordering matters: pyserial asserts DTR and RTS on open, which is esptool's reset-into-download-mode sequence on an ESP32-S3 native-USB CDC. Probing such a board does not merely fail — it can knock it out of operation.
3.0.2 May 3, 2026

Conformance re-verified against the frozen spec

  • All 195 tests across the conformance, compliance and RCAN 3 compliance suites pass against the post-freeze rcan-spec. No code changes — the release memorializes the verification outcome with a signed version-tuple envelope.
3.0.1 April 24, 2026

Two CLI gaps caught while recording the peer-runtime demo

  • castor init now matches the v3.0 wizard. The argparse registration was still the legacy shape and did not hit the wizard's expected attribute names.
  • castor validate ROBOT.md now works. The old handler always fed the target through yaml.safe_load, which errored on any ROBOT.md because the frontmatter-markdown format contains two --- documents.
3.0.0 Breaking April 24, 2026

ROBOT.md-native, full RCAN 3.x peer runtime

  • Version scheme change — CalVer (2026.4.23.0) → SemVer (3.0.0). The major signals peer-runtime alignment with rcan-spec 3.2, rcan-py 3.3 and rcan-ts 3.4.
  • Legacy .rcan.yaml input removed — runtime, register and compliance commands read ROBOT.md (v3.2 frontmatter) as the canonical source. The 2.x config path is rejected at ingress with a castor migrate hint.
  • castor/rcan3/ — the peer-runtime integration package: ROBOT.md reader with runtime selection, ML-DSA-65 + Ed25519 hybrid identity (private keys written 0o600 atomically, no chmod race), dict-level signer, async RRF client, the §22–26 compliance facade, and the Harness Protocol.
  • Removed — castor.config_validation (superseded by rcan-py's rcan.validate) and five legacy castor rrf subcommands.
v2026.3.27.1 RCAN v2.2 ML-DSA-65 March 27, 2026

RCAN v2.2 — Post-Quantum Primary • Dual-Brain • LLMFit • Hardware Stats

  • RCAN v2.2 — ML-DSA-65 primary — Ed25519 fully removed (not sunset-dated, removed). signature.alg = "ml-dsa-65" is the sole wire format. Legacy pq_sig field removed. Q-Day timeline accelerated from 2028 to 2026.
  • rcan-py v1.2.1 — 675 tests, MLDSAKeyPair, sign_message()/verify_message() with require_pq=True default. KeyPair stub redirects to MLDSAKeyPair with DeprecationWarning.
  • rcan-ts v1.2.1 — 545 tests, SignatureBlock.alg narrowed to literal "ml-dsa-65", pqSig removed from RCANMessageData.
  • Dual-brain architecture — brain_reactive (VLA/SLM, fast) + brain_planning (Claude/GPT, slow). Confidence gate at 0.60 — below escalates to planning brain. Wire field: brain added to action dict.
  • Production data wipe + re-registration — Firestore robots collection + RRF KV cleared. Bob (RRN-000000000001) re-registered with new ML-DSA-65 key, dual-brain configured.
  • castor conformance L5 — Full RCAN v2.2 compliance report across 6 domains. Score formula: max(0, 100 − failed×10 − warned×3). Bob scores 100/100. GET /api/conformance endpoint added.
  • castor iso-check — ISO 13482, ISO 10218-2, ISO 42001, EU AI Act Art. 12/13/14/15/16j self-assessment. Bob: COMPLIANT (self-declared). EU AI Act deadline: August 2, 2026.
  • castor llmfit — Model-fit checker: BF16 weight estimate + KV cache + overhead vs device RAM. TurboQuant 2.6× compression. MoE-aware. psutil-optional with /proc/meminfo fallback.
  • castor/system_info.py — Real hardware stats in /api/status: RAM, disk, CPU temp, NPU detection (Hailo-8/8L, Coral TPU, Qualcomm HTP), GPU, active model size, context window, llmfit headroom, tok/s. Auto-flows to Firestore via 30s telemetry push.
  • opencastor-client hardware stats — Robot detail screen shows live RAM, disk, CPU °C, NPU+TOPS, GPU, model+size, TurboQuant KV status, llmfit headroom, and tok/s as pill chips.
  • DISCOVER iso_conformance block — RCAN DISCOVER (msg_type=1) now includes iso_conformance block. rcan_version bumped to "2.2" in all gateway endpoints.
  • OpenCastor gateway: GET /api/attest, POST /api/attest/verify, GET /api/sbom, GET /api/sbom/download, GET /api/conformance.
  • opencastor-client: AttestationCard + compliance report button on robot detail. /robot/:rrn/attestation alias route.
v2026.3.21.1 March 21, 2026

Competition Engine — Sprint, Threshold Race & Bracket Seasons

  • Sprint format — time-boxed competitions with announced prize pools, tiered payout (50/30/20), anti-snipe 1h lock (castor/competitions/sprint.py)
  • Threshold Race — jackpot mechanic, first robot to hit target score wins, 3× independent verification re-run with 2% tolerance (castor/competitions/threshold_race.py)
  • Model×Hardware Bracket Seasons — monthly seasons, 5 hardware×model classes, class champions (2000/1000 credits), grand champion bonus 5000 credits (castor/competitions/bracket_season.py)
  • Competition API endpoints: GET/POST /api/competitions, /api/competitions/races, /api/seasons/current
  • Gemini 2.5 migration — all Gemini 2.0/1.5 model strings updated ahead of June 2026 deprecation
  • Contribute 10× throughput — Firestore client and queue state now cached; fetch latency 4.6s → 14ms
  • Auto-start contribute on gateway startup via agent.contribute config
v2026.3.19.0 March 19, 2026

castor contribute — Idle Compute for Distributed Science

  • castor contribute start|stop|status|projects CLI — donate idle NPU/CPU cycles to climate modeling, biodiversity monitoring, protein folding, and humanitarian AI
  • BOINC, Folding@home, and OpenCastor coordinator support with configurable project allowlists
  • P66-safe: any incoming command preempts contribute work within 100ms via ContributeCancel
  • Hardware-aware work unit matching: Hailo-8L HEF models, CPU fallback, optional camera/microphone sensor projects
  • Power-capped (max_power_w) and CPU-throttled (max_cpu_pct) to respect thermal/battery budgets
  • GET /api/contribute endpoint — live status, stats, and hardware profile
  • Fleet dashboard integration: per-robot contribution stats, active project indicator, enable/disable toggle
  • Privacy mode respected — contribute auto-pauses when castor privacy on is active
v2026.3.20.4 Harness Optimizer March 20, 2026 (afternoon)

Harness autoresearch live · editor UX overhaul · hardware-profile optimization

  • Autoresearch pipeline live — Gemini 2.0 Flash generates harness candidates nightly; winner pushes directly to main (no PRs). First champion: lower_cost (cost_gate_usd 0.05→0.01, score 0.9101)
  • Harness editor overhaul — smart type-aware block placement; zoom controls (+/−/fit); drag-to-connect edges; block info overlay (ℹ️); auto-connect on add; list↔flow graph sync
  • Connector type picker — tap any edge midpoint to label it YES/NO/loop/error/timeout/data/fallback or delete it
  • Capabilities screen fix — crash on gray screen resolved (safe Map→List cast); Cloud Function 403 resolved (firebase_uid ownership check)
  • Hardware-profile harness optimization — roadmap: contribute fleet runs tier-specific evals; per-profile champions for Pi5+Hailo, Pi4, Waveshare, Unitree, server. Blog post
  • castor provider CLI — castor provider auth/list/status for gated model providers
  • Harness per-layer provider routing — specify model: provider/name per layer; get_provider_for_layer() resolves with fallback
  • PyPI v2026.3.20.4 published via OIDC Trusted Publisher; RCAN schema relaxed (40/40 configs pass)
v2026.3.26.0 RCAN v1.10 March 26, 2026

RCAN v1.10 — Competition Protocol (types 37–40)

  • RCAN v1.10 canonical MessageType table — 40 message types. Added COMPETITION_ENTER (37), COMPETITION_SCORE (38), SEASON_STANDING (39), PERSONAL_RESEARCH_RESULT (40).
  • Competition protocol — robots can announce competition entry, publish verified scores, receive fleet-broadcast season standings, and log private personal research results.
  • rcan-py v0.9.0 — rcan/competition.py, 32 new tests, 663 total. SPEC_VERSION 1.10.0.
  • rcan-ts v0.9.0 — src/competition.ts, 28 new tests, 499 total. SPEC_VERSION 1.10.0.
  • rcan-spec — competitions.astro spec page with full protocol, payload schemas, and wire examples.
  • OpenCastor runtime accepts rcan_version: "1.10" / "1.10.0" in robot configs.
v2026.3.20.4 RCAN v1.8 March 20, 2026

RCAN v1.8 — Canonical MessageType & Idle Compute Contribution

  • RCAN v1.8 canonical MessageType table — 36 message types with fixed integer assignments. Single source of truth across spec, rcan-py, and rcan-ts. Zero drift.
  • castor contribute — donate idle NPU/GPU/CPU compute to distributed science. BOINC coordinator, NPU-optimized runner (Hailo-8L), fleet coordination, thermal throttling, P66 preemption.
  • CLI: castor contribute start/stop/status/history, castor peer-test with transport comparison
  • API: /api/contribute/start, /api/contribute/stop, /api/contribute/history
  • RCAN-MQTT transport wired into runtime — rcan/{rrn}/in, rcan/{rrn}/out, rcan/estop topics
  • Software attestation — pip RECORD hash check, config SHA256 baseline, git cleanliness; systemd service template
  • Security fixes — RCAN-Signature bypass, None-principal scope skip, WebSocket JWT bypass, SSRF, LoA default hardening
  • rcan-py v0.7.0 (609 tests), rcan-ts v0.7.0 (447 tests), opencastor-client v1.1.0+2
  • Fleet contribution dashboard, history timeline, project selection UI in Flutter client
  • Blog: "From Robot Runtime to Climate Sensor"
v2026.3.17.1 March 17, 2026

RCAN v1.6 — Federation, Constrained Transports, Multi-Modal, Identity LoA

  • GAP-16: Registry Federation Protocol — FEDERATION_SYNC wire format, cross-registry JWT trust chains, 3-tier registry hierarchy (root/authoritative/community), DNSSEC trust anchor discovery
  • GAP-17: Bandwidth-constrained transports — RCAN-Minimal (32-byte ESTOP for LoRa/BLE), RCAN-Compact (CBOR, <200 bytes ESTOP), BLE L2CAP framing
  • GAP-18: Multi-modal payloads — media_chunks[] field, SHA-256 audit trail, streaming mode, TRAINING_DATA now requires media payload
  • GAP-14: Human identity LoA 1/2/3 — FIDO2 binding, registry trust tiers, min_loa_for_control in P66 manifest
  • All 22 original security/safety audit gaps addressed
  • castor setup wizard: interactive onboarding with inline QR codes, castor bridge setup, castor fleet-link
  • rcan-py v0.6.0 (587 tests), rcan-ts v0.6.0 (405 tests)
v2026.3.17.0 RCAN v1.5 March 17, 2026

RCAN v1.5 — Production Safety Hardening (18 gaps addressed)

  • GAP-03: Replay attack prevention — 30s sliding window seen-set, 10s for safety messages
  • GAP-02: Robot identity revocation — ROBOT_REVOCATION broadcast, 1h TTL cache
  • GAP-01: Command delegation chains — 4-hop max, Ed25519-signed, audit trail
  • GAP-05: Consent wire protocol — CONSENT_REQUEST/GRANT/DENY on-wire format
  • GAP-11: ESTOP QoS exactly-once delivery — retry until ACK, SafetyHaltError on timeout
  • GAP-06: Offline operation mode — 300s grace, ESTOP always allowed
  • GAP-10: Training data consent — EU AI Act Art.10, DataCategory enum
  • GAP-08: Cloud relay identity audit — sender_type: cloud_function
  • Protocol 66 conformance: 87% → 94%
  • rcan-py v0.5.0 (430 tests), rcan-ts v0.5.0 (311 tests)
v2026.3.14.6 2026-03-14
CI Fixes + Driver Migrations
  • Fixed castor doctor crash (#672)
  • Migrated 18 hardware drivers to _move() for automatic SafetyLayer routing (#673)
  • Fixed waveshare_alpha.rcan.yaml schema validation
  • DriverBase.move() accepts dict and linear_x/angular_z kwargs (backward compat)
  • 736 tests passing, 7 skipped
v2026.3.14.5 2026-03-14
Safety (Protocol 66 full implementation)
  • SensorMonitor now wires to SafetyLayer.estop() — thermal/electrical critical events halt motors
  • SO-ARM101 safety_bridge.py — all arm commands route through SafetyLayer (bounds, estop, rate limits, anti-subversion, full audit)
  • Per-scope RCAN §16.2 confidence gates: CONTROL=0.75, CONFIG=0.65, TRAINING=0.60, STATUS=0.0
  • Session expiry → controlled stop for CONTROL-scoped principals (RCAN §6)
  • Remote RCAN commands tagged source=rcan in every audit log entry
  • 11 adversarial P66 invariant tests proving all 5 invariants hold
  • GET /api/safety/manifest endpoint — live conformance report
  • DriverBase SafetyLayer integration — hardware drivers opt in via _move()
  • hardware_safety field in rcan-config.json schema (physical_estop, SIL level, etc.)
  • 6 new conformance checker safety checks (P66 conformance %, local_safety_wins, watchdog, etc.)
Code quality
  • Fixed 13 BoundsStatus type errors, p66_manifest typing, pca9685 None guards
  • ws_telemetry complexity reduced from 26 to 3 (extracted _build_telemetry_payload)
  • rcan-py 0.4.1: safety message helpers (make_estop/stop/resume, validate_safety_message)
Ecosystem
  • RCAN schema: local_safety_wins is now a required field (RCAN §6 invariant)
  • All 5 RRF robot entries have hardware_safety capability declarations
  • castor init generates complete safety block by default
  • rcan.dev/docs/safety — new safety conformance documentation page
v2026.3.13.12 2026-03-13
Changed
  • CLAUDE.md: complete rewrite for RCAN v1.4 — MessageType 16/17, RRN URI format, TieredBrain routing, JS SDK §19/§21 examples
  • rcan_version in all config examples updated to "1.4"
  • README updated for v1.4 spec alignment
Ecosystem
  • rcan-py: v0.3.1 → v0.4.0 (SPEC_VERSION 1.4)
  • rcan-spec: v1.3 → v1.4 (§1–§16 dedicated section pages)
v2026.3.13.11 2026-03-13
Fixed
  • castor/rcan/registry.py: _validate_rrn() now accepts numeric RRN-XXXXXX format alongside URI format; type-check for non-string input raises ValueError not AttributeError
  • castor/rcan/registry.py: RegistryRegisterResult.from_message() enforces rrn required on success, error required on failure
  • castor/rcan/registry.py: RegistryResolveResult.from_message() enforces ruri required when status="found"
  • castor/rcan/registry.py: RegistryResolveResponse.to_message() emits correct wire type REGISTRY_RESOLVE_RESULT (17), not REGISTRY_RESOLVE (14)
  • castor/tiered_brain.py: sensor_poll fast-only guarantee enforced — interpreter should_escalate can no longer override planner suppression
  • castor/rcan/sdk_compat.py: handle rcan ≥ 0.3.0 ValidationResult object return from validate_config()
  • bob.rcan.yaml: added rrn, rrn_uri, task_routing block; updated to v2026.3.13.11
Added
  • 15 new validation tests in tests/test_rcan_registry.py covering Copilot-flagged validation paths; 105 total passing
v2026.3.13.10 2026-03-13
Fixed
  • castor/fleet/group_policy.py: FleetManager.from_config now emits logger.warning on malformed group entries instead of silently dropping them (#641)
Added
  • tests/test_fleet_group_policy.py: 28 tests covering GroupPolicy.matches, FleetManager, resolve_config, and _deep_merge (#640)
v2026.3.13.9 2026-03-13
Added
  • castor/providers/task_router.py: add openrouter to all task categories in _DEFAULT_ROUTING — was unreachable (#639)
  • tests/test_task_router.py: 3 new tests validating openrouter reachability, local-provider priority for SENSOR_POLL, cloud-fallback for REASONING
v2026.3.13.8 March 13, 2026 Current
🧠

Task-Aware Model Routing

castor/providers/task_router.py: selects provider by task category (SENSOR_POLL, NAVIGATION, REASONING, CODE, SEARCH, VISION, SAFETY). SAFETY tier never downgrades. (#612)

🧪

OpenRouter Provider Test Coverage

tests/test_openrouter_provider.py: test_model_name_defaults_when_not_configured pins _DEFAULT_MODEL to anthropic/claude-3.5-sonnet; regressions caught by CI. (#637)

🔧

Ruff Import Cleanup

Unused imports removed and blank lines normalized across multiple test files.

v2026.3.13.7 March 13, 2026
🔧

OpenRouter Default Model Updated

castor/providers/openrouter_provider.py: _DEFAULT_MODEL updated from anthropic/claude-3.5-haiku to anthropic/claude-3.5-sonnet to align with the current ecosystem-standard model. (#635)

v2026.3.13.6 March 13, 2026
🔒

RCAN Dependency Constraint Tightened

pyproject.toml: rcan dependency constraint tightened from >=0.1.0 to >=0.3.0,<1.0. Aligns with minimum SDK version required for RCAN v1.3 §17/§19 features (INVOKE_CANCEL, Ed25519 signing). Applies to core deps and [rcan] extras group. (#634)

v2026.3.13.5 March 13, 2026
🔧

RCAN §21 MessageType Additions

castor/rcan/message.py: add REGISTRY_REGISTER_RESULT (wire value 16) and REGISTRY_RESOLVE_RESULT (wire value 17) to MessageType enum per RCAN spec §21. (#631)

🔒

SDK Compatibility Version Bump

castor/rcan/sdk_compat.py: minimum rcan-py version check bumped from >=0.2.0 to >=0.3.0. tests/test_compliance.py: fixture updated from "0.1.0" to "0.3.0". (#630 #632)

v2026.3.13.4 March 13, 2026
🚀

Deploy Workflow Self-Trigger Fix

.github/workflows/deploy-pages.yml: workflow file added to path filter so wrangler-action SHA bumps self-trigger a deploy. (#625)

🗺️

Sitemap & robots.txt

site/sitemap.xml and site/robots.txt added; sitemap covers all 8 top-level pages with change-frequency and priority hints for search crawler discovery. (#627)

🔗

OG & Twitter Meta Tags

Open Graph and Twitter Card meta tags added to about.html, docs.html, changelog.html, hardware.html, beginners.html, and tutorials.html. Unblocks social link previews. (#626)

v2026.3.13.3 March 13, 2026
🔗

RCAN v1.3 Migration Chain

castor/migrate.py: implements full migration chain 1.0.0-alpha → 1.1 → 1.2 → 1.3; configs can now be fully upgraded to CURRENT_VERSION without hitting an empty path. (#619)

🔧

Config Template & Conformance Fixes

castor/setup_service.py default new config template now generates rcan_version: "1.3". castor/conformance.py fix-hint messages updated to reference v1.3. Hardware doc YAML examples (lerobot-kits.md, reachy.md) updated. (#620 #621)

v2026.3.13.2 March 13, 2026
⚡

INVOKE_CANCEL + ParallelSkillExecutor

InvokeCancelRequest dataclass for INVOKE_CANCEL wire messages (§19.4). InvokeResult.status adds "cancelled" variant. SkillRegistry.cancel(msg_id) with threading.Event tracking for best-effort in-flight cancellation. New ParallelSkillExecutor with fan-out and race semantics. (#609 #610 #616)

🧪

TestInvokeFamily Suite

9 tests covering INVOKE routing, INVOKE_CANCEL (found / not-found / missing-msg-id), no-registry error, INVOKE_RESULT type, and routed counter increment. (#611)

v2026.3.13.1 March 13, 2026
🔌

INVOKE_CANCEL MessageType + Timeout Enforcement

MessageType.INVOKE_CANCEL = 15 added to RCAN v1.3 §19 compliance. SkillRegistry.invoke() now executes in a ThreadPoolExecutor and enforces timeout_ms via future.result(timeout=...), returning status="timeout" immediately on deadline expiry. (#607 #608)

🧪

Concurrent + Timeout Invoke Tests

TestTimeoutEnforcement and TestConcurrentInvoke suites added to tests/test_rcan_invoke.py. (#605)

v2026.3.13.0 March 13, 2026
🧠

Episodic Memory + Rolling Compression

SQLite-backed episodic memory with recall and inject_context(). Shared-context ThreadContextBus. Rolling context compression for 24/7 continuous operation (configurable token budget, summary injection). (#613 #614 #615)

📋

RCAN v1.3 Spec Alignment

SPEC_VERSION updated to "1.3". rcan_version references in CLI, registry, and conformance output updated. Generated config template bumped to "1.3.0". Health probe exceptions promoted to WARNING level. (#603 #606)

v2026.3.12.0 March 11, 2026 Current
🔍

castor scan / doctor / upgrade / stop

castor scan CLI subcommand prints full hardware scan with --json, --refresh, --preset-only flags. castor doctor now warns on missing optional packages for detected devices (depthai, reachy2-sdk, etc.). castor upgrade does git pull + pip install + service restart in one command with --check and --venv PATH flags. castor stop reads ~/.opencastor/gateway.pid and sends SIGTERM for clean shutdown.

🛡️

Gateway Hardening + Venv-Agnostic Systemd

Gateway writes a PID file to ~/.opencastor/gateway.pid and detects port-in-use on startup. Systemd service templates now use python -m castor.cli gateway and python -m streamlit run instead of binary paths — survives venv migrations. Services include KillMode=control-group, TimeoutStopSec=15, SendSIGKILL=yes, and ExecStartPre port cleanup. detect_hardware() gets a 30-second TTL cache with invalidate_hardware_cache().

🐛

Bug Fixes

scservo-sdk renamed to feetech-servo-sdk in [lerobot] extras — package now exists on PyPI. OAK-D SR (VID/PID 03e7:f63b) lsusb output now normalized to lowercase before model name lookup — no longer misdetected as bootloader/lite. LIBCAMERA_LOG_LEVELS=*:FATAL set at import time to suppress noisy libcamera stderr during scans.

📖

Upgrade Guide

New docs/install/upgrade.md covering Pi OS PEP 668, --system-site-packages venv setup, systemd service migration, and troubleshooting common install errors.

v2026.3.11.0 March 11, 2026
🔌

Plug-and-Play Hardware Auto-Detection

castor scan now identifies 12+ hardware types by USB VID/PID, I2C address, PCIe, and mDNS network discovery: Intel RealSense D4xx/L515, Luxonis OAK-D family, ODrive v3/Pro/S1, VESC, Hailo-8 NPU, Google Coral USB/M.2, Arduino (official + CH340/FTDI clones), Adafruit CircuitPython, Dynamixel U2D2, RPLidar, Raspberry Pi AI Camera (IMX500), and Pollen Robotics Reachy. I2C address lookup for 10+ common sensors. USB descriptors memoized — lsusb called once per scan. Hot-plug support via invalidate_usb_descriptors_cache().

🦾

Feetech STS3215 Driver + LeRobot Profiles

New FeetechDriver for Feetech SCS/STS serial bus servos used in SO-ARM100/101 and LeRobot kits. port: auto detects the CH340 USB adapter automatically. Pre-built RCAN profiles: lerobot/so-arm101-follower, lerobot/so-arm101-leader, lerobot/so-arm101-bimanual, lerobot/koch-arm (Dynamixel XL430/XL330 via U2D2), lerobot/aloha (bimanual). Install: pip install opencastor[lerobot]. Fixes CH340 clone misrouting to Arduino Nano.

🤖

Pollen Robotics Reachy Driver

New ReachyDriver for Reachy 2 and Reachy Mini via reachy2-sdk (gRPC). host: auto uses concurrent mDNS hostname probes (reachy.local / reachy-mini.local) with no blocking getaddrinfo calls. Profiles: pollen/reachy2.yaml, pollen/reachy-mini.yaml. Install: pip install opencastor[reachy].

🔧

Bug Fixes

detect_feetech_usb() no longer misroutes Arduino Nano CH340 clones to LeRobot SO-ARM101 profile. _auto_detect_vesc_port() ODrive-USB fallback removed (prevented ODrive port being opened as VESC serial). print_scan_results() now includes all detected categories. suggest_preset() correctly distinguishes Reachy Mini from Reachy 2.

v2026.3.10.1 March 10, 2026
🧠

EmbeddingInterpreter — Local Semantic Memory

New EmbeddingInterpreter subsystem gives robots semantic memory via local CLIP embeddings (512-dim, no API key required). Three-tier backend: CLIP (free, default) → ImageBind (6-modality, experimental) → Gemini Embedding 2 (3072-dim MRL, premium). Episode store with RAG context injection into every brain tick. Configure with a single RCAN block under perception.embeddings. Zero config to start.

⚙️

HLabs ACB v2.0 — BLDC Motor Controller Driver

First-class driver for HLaboratories' open-source Actuator Control Board. STM32G474 MCU, 12V–30V, 40A max, CAN Bus at 1Mbit/s. Auto-detects via USB VID/PID, runs full calibration sequences, streams 50Hz encoder telemetry to the dashboard. Pre-built profiles for single actuator, 3-DOF arm, and 6-DOF biped. Firmware flash via DFU. Install: pip install opencastor[hlabs]. RCAN protocol: hlabs_acb.

v2026.3.8.3 March 8, 2026
🗄️

EpisodeStore FIFO Cap

Episode memory is now capped at 10,000 entries with automatic FIFO eviction. Prevents unbounded disk growth on long-running robots.

🔧

ApplyStage Deduplication

The SisyphusLoop ApplyStage now deduplicates patches before writing, preventing redundant writes in tight improvement cycles.

🕐

Timezone-Aware Datetimes

All timestamps in the episode store, usage tracker, and audit log are now timezone-aware UTC. Fixes comparison warnings with Python 3.12+.

v2026.3.8.2 March 8, 2026
😊

Robot Face with Closed Captions

Dashboard robot face now renders live closed captions of the robot's speech output. Font size and display duration configurable via RCAN.

🎮

Gamepad Page

New /gamepad dashboard page for manual control via browser-connected gamepads. Maps standard buttons to move/stop/grip actions.

🧠

Brain Model Visibility

Active brain model name now shown in the dashboard status bar and in the /api/status response under brain.model.

✨

Dashboard UX Improvements

Consolidated telemetry panel, faster chart rendering, improved mobile layout, and sticky header in the thought history view.

v2026.3.8.0 March 6, 2026
🛡️

RCAN-Swarm Safety

New swarm safety layer enforces RCAN §16 AI Accountability across all swarm nodes. Commands carry model identity, confidence gates, and HITL authorization tokens. Nodes reject commands that fail the safety manifest.

🖥️

castor node CLI

New castor node command group for managing individual swarm nodes: castor node status, castor node logs, castor node restart.

🧪

castor register --dry-run

castor register now accepts --dry-run to validate RCAN config and registration payload without actually registering the node. Useful in CI/CD pipelines.