← Back to PRs

#14704: Add PIC Standard plugin for intent verification

by madeinplutofabio open 2026-02-12 14:25 View on GitHub →
size: XL
**PIC Standard plugin for OpenClaw** — enforces Provenance & Intent Contracts on tool calls. - **Python verifier** exposed via production-ready HTTP bridge (`pic-cli serve`) - **`before_tool_call` hook** POSTs to `/verify` with `{ tool_name, tool_args }` - **Structured responses** — `allowed: true/false` with detailed error codes - **Fail-closed design** — bridge unreachable = tool blocked - **Full logging, config, and PIC awareness injection** at session start Verifier code: [`pic_standard/verifier.py`](https://github.com/anthropics/pic-standard) (also supports CLI and evidence verification via `--verify-evidence`) @divol89 Related to: https://github.com/openclaw/openclaw/issues/9753 <!-- greptile_comment --> <h3>Greptile Summary</h3> This PR adds a new `pic-guard` extension that enforces Provenance & Intent Contracts (PIC) on tool calls via three hooks and an HTTP bridge client. While the core HTTP client (`pic-client.ts`) is well-designed with proper fail-closed semantics, the plugin's hook handlers have several critical issues that prevent them from working correctly with the OpenClaw plugin API: - **`pic-init` handler (broken)**: Mutates `event.messages.push()` to inject PIC awareness, but the `before_agent_start` hook system reads the **return value** (`{ prependContext?, systemPrompt? }`), not event mutations. The awareness message will never be injected. - **`pic-audit` handler (broken)**: Expects `{ toolName, params, result, error, durationMs }` but the real `tool_result_persist` event is `{ toolName?, toolCallId?, message, isSynthetic? }`. All audit fields will be undefined at runtime. - **Config loading (broken in all 3 handlers)**: All handlers read `ctx?.pluginConfig` but the hook contexts (`PluginHookToolContext`, `PluginHookAgentContext`) do not include `pluginConfig`. Config should be captured via closure from `api.pluginConfig` during registration. - **`package-lock.json` mismatch**: Lockfile names the package `@pic-standard/openclaw-plugin` while `package.json` names it `pic-guard`. - **Test files in `dist/`**: `tsconfig.json` doesn't exclude `*.test.ts`, so compiled test files end up in the distribution. <h3>Confidence Score: 1/5</h3> - This PR has multiple critical bugs where handlers use incorrect OpenClaw plugin API contracts, meaning 2 of 3 hooks will silently fail at runtime. - Score of 1 reflects that while the HTTP client and fail-closed design are sound, the plugin's integration with OpenClaw's hook system is fundamentally broken in multiple places: the init handler won't inject context, the audit handler reads non-existent event fields, and config loading fails silently in all handlers. Only the gate handler's core blocking logic would partially work (with default config). - Pay close attention to `extensions/pic-guard/hooks/pic-init/handler.ts` (broken event API), `extensions/pic-guard/hooks/pic-audit/handler.ts` (wrong event shape), and `extensions/pic-guard/hooks/pic-gate/handler.ts` (config loading from wrong source). <sub>Last reviewed commit: 5ae4a28</sub> <!-- greptile_other_comments_section --> <sub>(2/5) Greptile learns from your feedback when you react with thumbs up/down!</sub> **Context used:** - Context from `dashboard` - CLAUDE.md ([source](https://app.greptile.com/review/custom-context?memory=fd949e91-5c3a-4ab5-90a1-cbe184fd6ce8)) <!-- /greptile_comment -->

Most Similar PRs