Add robotics policy prover experiment and Dev Note - #36
Conversation
Documentation previewBuilt from |
| if decision.decision == Decision::Deny { | ||
| return Ok(()); | ||
| } | ||
| self.execute_decision(action, decision, executor_note).await |
There was a problem hiding this comment.
Thanks for making the decision packet and executor handoff so visible—this is a strong demo surface. Could we apply the returned contract before emitting execution here? In the repaired flow, the action still requests 0.18 m/s after the decision caps it at 0.08 m/s; additionally, the world reports human_distance_m = 0.48 while the returned obligation says to pause below 0.5 m, yet execution proceeds. That makes the audit event claim enforcement while still carrying the original over-limit action. I’d suggest materializing an effective action with speed/force constraints applied, evaluating active obligations before and during execution, emitting that effective envelope, and covering this path with an end-to-end test. -- Codex ;)
| self.world.metrics.p95_solver_ms = p95(&self.solver_samples); | ||
|
|
||
| let approved_path = match decision.decision { | ||
| Decision::Allow | Decision::AllowWithConstraints | Decision::ApprovalRequired => { |
There was a problem hiding this comment.
I appreciate the explicit four-way decision contract; it makes the policy boundary easy to understand. One important distinction gets lost here, though: ApprovalRequired receives an approved_path, and check_and_execute blocks only Deny, so an action that needs human approval can proceed without an approval transition. Could we reserve approved_path and execution for Allow/AllowWithConstraints, then add a test showing that ApprovalRequired remains stopped until explicit approval is recorded? -- Codex ;)
| title: "Can Formal Methods Govern AI-Generated Robot Actions? An OpenShell-Inspired Experiment" | ||
| date: 2026-08-07 | ||
| updated: 2026-08-07 | ||
| description: "A robotics experiment asks whether an independent, SMT-backed policy boundary can efficiently govern AI-generated plans before they reach a simulated or physical robot." |
There was a problem hiding this comment.
This is a compelling framing, and I’m grateful for how carefully the later limitations are discussed. I think the opening should be more explicit about the current Z3 role, however: solver.check() is run but its result is discarded, after which the facts and verdict are recomputed in Rust. Calling the boundary “SMT-backed” this early can therefore leave readers believing Z3 governs admission, while making the solver authoritative is identified much later as future work. Could we say up front—and again before the benchmark—that deterministic Rust rules currently produce the verdict while a non-authoritative Boolean Z3 composition check is executed and timed? Alternatively, making the solver result authoritative would support the current framing. -- Codex ;)
| Json(serde_json::json!({ "ok": true })) | ||
| } | ||
|
|
||
| async fn decide(Json(action): Json<ActionEnvelope>) -> Json<ProverDecision> { |
There was a problem hiding this comment.
Could we make this external decision boundary fail closed on malformed envelopes? An empty or one-waypoint path currently has no out-of-bounds point and no segment intersection, so it can return allow; from and to also do not need to agree with the path. Validating at least two finite waypoints, positive finite speed/force and zone dimensions, plus endpoint consistency—and adding malformed-envelope tests—would make the stated path invariants meaningful for callers. Thanks for exposing this endpoint cleanly; a little validation here would make it much more trustworthy. -- Codex ;)
| const progressRef = useRef(0); | ||
|
|
||
| useFrame((_, delta) => { | ||
| const shouldMove = path.length > 1 && step.decision !== "deny" && step.decision !== "pending"; |
There was a problem hiding this comment.
The event-by-event visualization is a really helpful way to explain the boundary. Could movement begin only on execution_update rather than as soon as a prover decision exposes an approved_path? Today the scene starts animating during the intentional 600 ms gap before the executor event, which undercuts the UI’s “checks before anything moves” explanation. Keeping a proven candidate path separate from the actively executing path, with a browser assertion for this transition, would preserve the story the demo is telling. -- Codex ;)
|
|
||
| <rect class="bg" width="1200" height="720" rx="18"/> | ||
| <text class="title" x="50" y="49">A practical boundary between an AI agent and physical effects</text> | ||
| <text class="body" x="50" y="77">The agent operates inside a sandbox; the runtime admits each proposed plan or action before it reaches a simulator or robot.</text> |
There was a problem hiding this comment.
This diagram does an excellent job of making the intended boundary legible. Could we label it explicitly as the target/OpenShell-inspired architecture, and visually distinguish the implemented path (planner → Rust service → Three.js) from future pieces? As drawn, the sandboxed non-bypassable runtime, Isaac Sim, MuJoCo, and real robot look like parts of the recorded prototype, while the note later identifies them as next experiments. A small current-versus-target cue would keep readers oriented without losing the broader vision. -- Codex ;)
| .route("/api/sessions/{id}/events", get(session_events)) | ||
| .route("/api/sessions/{id}/inject", post(inject_event)) | ||
| .route("/api/decide", post(decide)) | ||
| .layer(CorsLayer::permissive()) |
There was a problem hiding this comment.
Since the Vite app already proxies /api from the same origin, could we remove permissive CORS or restrict it to an explicitly configured frontend origin? With OPENAI_API_KEY configured, an arbitrary page may be able to create localhost sessions that trigger billable model calls, and completed sessions remain in the map. I’d also consider bounding session creation and cleaning up completed sessions. The local-first setup is nicely straightforward; tightening this default would keep that experience safe. -- Codex ;)
| *We built a small robotics experiment to test whether OpenShell's approach to | ||
| policy enforcement can be applied to AI-generated robot plans.* | ||
|
|
||
| <figure class="dev-note-figure dev-note-figure--hero"> |
There was a problem hiding this comment.
Thanks for giving the experiment such a prominent visual entry point—the screenshot makes the issue clear. The source PNG is 2656×1820 (native ratio 664:455, about 1.46:1), but .dev-note-figure--hero img forces 1200 / 630 (about 1.90:1), so the rendered hero looks stretched. Could we preserve the image’s true aspect ratio here by removing/overriding that forced ratio for this asset (or setting it to 2656 / 1820)? One alternative worth trying is to move the recorded demo into this top hero position and let it autoplay so readers immediately see the experiment in motion. If we explore that, I’d keep it muted playsinline, retain controls and the poster fallback, use the video’s native aspect ratio, and respect reduced-motion preferences; we could then remove the duplicate video lower in the note. -- Codex ;)
| This experiment does not attempt to explain or verify everything happening | ||
| inside a model. It applies formal methods to a narrower artifact: the concrete | ||
| action proposed by the planner. |
There was a problem hiding this comment.
This “not X, but Y” structure, with a phrase like "...applies formal methods to a narrower artifact:" is a bit too AI for me 🙃. Might be worthwhile to have a few passes to catch stuff like this.
Summary
projects/robotics-policy-proverScope and caveats
Validation
python3 tests/test_render_dev_notes.py— 11 passedscripts/build-docs.sh— clean strict Zensical build and all rendered-site checks passednpm run build— production frontend build passednpm audit— 0 vulnerabilities after refreshing Vite/PostCSS within their existing compatible rangescargo test --release --manifest-path policy-prover-service/Cargo.toml— 4 passed