[luv-338] fix: canonicalize OpenCode + Pi tool-input arg keys#337
[luv-338] fix: canonicalize OpenCode + Pi tool-input arg keys#337NiveditJain merged 3 commits intomainfrom
Conversation
…-checking builtins fire
OpenCode's `read` slipped past `block-read-outside-cwd`: the shim
canonicalized the tool name (`read` → `Read`) but forwarded `output.args`
verbatim. OpenCode delivers `{ filePath }`; the policy reads
`ctx.toolInput.file_path`, so `getFilePath()` returned "" and the
target-empty short-circuit at builtin-policies.ts:799 allowed the read.
Same family of bug on Pi with a different mismatch shape: Pi's
read/write/edit use `path`. `block-read-outside-cwd` happens to work
on Pi via the existing `tool_input.path` fallback at builtin-policies.ts:796,
but `block-env-files` and `block-secrets-write` only check `file_path`
and were silently no-op'd.
Mirrors the TOOL_NAME_MAP pattern from #293 with two new per-tool
input-key maps keyed by canonical PascalCase tool name:
• OPENCODE_TOOL_INPUT_MAP — Read/Write/Edit: filePath→file_path,
plus oldString/newString/replaceAll for Edit
• PI_TOOL_INPUT_MAP — Read/Write/Edit: path→file_path
(Pi's nested edits[{oldText,newText}] array doesn't flat-rename,
no current builtin reads it)
Both maps are mirrored inline in their shims so .opencode/plugins/
failproofai.mjs and pi-extension/index.ts stay self-contained. MCP
mcp_* and any unmapped tool pass through unchanged.
Existing users must re-run `failproofai policies --install --cli opencode`
/ `--cli pi` to regenerate their shims and pick up the fix.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
…P in configuration.mdx Mirror the existing tool-name canonicalization wording in the OpenCode and Pi sections. Calls out which builtin policies start firing as a result (block-read-outside-cwd / block-env-files / block-secrets-write on OpenCode; block-env-files / block-secrets-write on Pi). Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
📝 WalkthroughWalkthroughThis PR fixes a mismatch between tool-input argument key formats across OpenCode and Pi integrations. Tool input keys from these CLIs (e.g., OpenCode's ChangesTool Input Canonicalization
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~20 minutes Possibly related PRs
Poem
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches📝 Generate docstrings
Tip 💬 Introducing Slack Agent: The best way for teams to turn conversations into code.Slack Agent is built on CodeRabbit's deep understanding of your code, so your team can collaborate across the entire SDLC without losing context.
Built for teams:
One agent for your entire SDLC. Right inside Slack. Comment |
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
There was a problem hiding this comment.
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
CHANGELOG.md (1)
3-7:⚠️ Potential issue | 🟠 Major | ⚡ Quick winUpdate the changelog section date to today (2026-05-10).
The entry is under
0.0.10-beta.10but the section header date is2026-05-09; repository policy requires the current version section date to match today for the PR update.Suggested patch
-## 0.0.10-beta.10 — 2026-05-09 +## 0.0.10-beta.10 — 2026-05-10As per coding guidelines, "Every PR must include an update to CHANGELOG.md under the current '## — ' section matching package.json version and today's date."
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@CHANGELOG.md` around lines 3 - 7, Summary: The CHANGELOG.md entry for version 0.0.10-beta.10 has the wrong date (2026-05-09) and must be updated to today's date. Fix: open CHANGELOG.md, find the header "## 0.0.10-beta.10 — 2026-05-09" and change the date to "2026-05-10" so the section header matches the current PR date; ensure the version string "0.0.10-beta.10" remains unchanged and save the file.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Outside diff comments:
In `@CHANGELOG.md`:
- Around line 3-7: Summary: The CHANGELOG.md entry for version 0.0.10-beta.10
has the wrong date (2026-05-09) and must be updated to today's date. Fix: open
CHANGELOG.md, find the header "## 0.0.10-beta.10 — 2026-05-09" and change the
date to "2026-05-10" so the section header matches the current PR date; ensure
the version string "0.0.10-beta.10" remains unchanged and save the file.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
Run ID: 7b1f3c77-e04c-4ae2-855b-5ffca130aac4
📒 Files selected for processing (8)
CHANGELOG.md__tests__/e2e/hooks/opencode-integration.e2e.test.ts__tests__/hooks/opencode-plugin-shim.test.ts__tests__/hooks/pi-extension-shim.test.tsdocs/configuration.mdxpi-extension/index.tssrc/hooks/integrations.tssrc/hooks/types.ts
…zation for OpenCode/Pi (#340) * [luv-340] fix: regenerate OpenCode dev shim + add handler-side canonicalization for OpenCode/Pi Two-layer fix for `block-read-outside-cwd` silently no-op'ing on OpenCode inside this repo. PR #337 added `OPENCODE_TOOL_INPUT_MAP` to the production shim template at `src/hooks/integrations.ts:buildOpenCodePluginShim`, but the dev shim at `.opencode/plugins/failproofai.mjs` is hand-maintained and was never regenerated, so contributors running `opencode` from inside this repo could still read paths outside the repo cwd — `getFilePath()` returned "" (camelCase `filePath` didn't match the policy's snake_case `file_path` lookup) and the target-empty short-circuit at `src/hooks/builtin-policies.ts:799` returned allow. Layer 1 (dev shim): regenerate `.opencode/plugins/failproofai.mjs` to mirror the production template — `TOOL_NAME_MAP` + `TOOL_INPUT_MAP` + idempotent `canonicalizeTool` / `canonicalizeToolInput`. Also pick up the `applyDecision` async-await change from #318 that the dev shim had been missing, so Stop / SubagentStop force-retry actually awaits the SDK call before the plugin handler returns. Layer 2 (handler): add per-CLI canonicalization for OpenCode + Pi in `src/hooks/handler.ts` as defense-in-depth, so a user-scope shim that pre-dates #337 automatically starts enforcing the moment failproofai upgrades — without forcing a `failproofai policies --install --cli opencode` re-run. The shim canonicalization stays in place; both passes are idempotent because the per-CLI maps key on camelCase / Pi-shape and don't match already-canonical snake_case input. New `canonicalizeToolInput` helper is gated by `cli === "opencode" / "pi"` so Claude / Codex / Cursor / Copilot / Gemini sessions are unaffected. New unit tests in `__tests__/hooks/handler.test.ts` cover: - Stale-shim shapes (`read` + `filePath` for OpenCode, `read` + `path` for Pi) - Per-CLI map coverage parity (12 OpenCode + 6 Pi tool names, four Edit keys) - Idempotency (handler doesn't corrupt fresh-shim shapes) - Unknown-tool passthrough (MCP `mcp_*` tool names + args) - Per-CLI gate (Claude payloads with literal `filePath` keys are not rewritten) Smoke-tested against the exact pattern from the bug report: an opencode `read` with a camelCase `filePath` pointing outside the repo cwd is now blocked with a clear `Access outside project directory blocked` deny reason. In-cwd reads still pass. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com> * [luv-340] chore: align CHANGELOG date with UTC for 0.0.10-beta.11 section CodeRabbit flagged the freshly-added section heading dated 2026-05-09 while the PR was opened at 2026-05-10T02:26Z UTC. Bump the date so the heading is internally consistent with the prior `## 0.0.10-beta.10 — 2026-05-10` section and with the GH server clock that downstream release tooling reads. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com>
Summary
ses_1f0e1c55affeZUG6LBf95r6eRz(CWD/home/nivedit/dev-purge) successfully read/home/nivedit/claudeye— outside its CWD — via thereadtool.block-read-outside-cwddid not deny it.read→Read) but forwardsoutput.argsverbatim. OpenCode delivers{ filePath: "..." }; the policy readsctx.toolInput.file_path, sogetFilePath()returns""and the empty-target short-circuit atsrc/hooks/builtin-policies.ts:799allows the read.read/write/editusepath.block-read-outside-cwdhappens to work on Pi via an existingpathfallback (builtin-policies.ts:796), butblock-env-filesandblock-secrets-writeonly checkfile_pathand were silently no-op'd.*_TOOL_MAPpattern with per-tool input-key maps:OPENCODE_TOOL_INPUT_MAP— Read/Write/Edit:filePath→file_path, plusoldString/newString/replaceAllfor EditPI_TOOL_INPUT_MAP— Read/Write/Edit:path→file_path(Pi nested edits-array doesn't flat-rename; no current builtin reads it).opencode/plugins/failproofai.mjsandpi-extension/index.tsstay self-contained. MCPmcp_*and any unmapped tool pass through unchanged.Existing OpenCode/Pi users must reinstall their shim via
failproofai policies --install --cli opencode/--cli pito pick up the fix.Test plan
bun run test:run— 1588 unit tests pass (added 5 OpenCode-shim tests + 6 Pi-shim tests covering filePath / path translation, all four Edit keys, mcp_* passthrough, after-hook canonicalization, and exported-map parity)bun run test:e2e— 297 e2e tests pass (added regression inopencode-integration.e2e.test.ts: Read of a path outside cwd hitsblock-read-outside-cwddeny)bun run lint— clean (one pre-existing unrelated warning)bun run build— Next.js + dist build cleanfailproofai policies --install --cli opencode --scope project, start OpenCode session in a new CWD, ask to read a path outside the CWD → expect deny🤖 Generated with Claude Code
Summary by CodeRabbit
Bug Fixes
Documentation
Tests