Skip to content

fix(hooks): pass user-configured policyParams to custom policies (#585) - #616

Open
AVPthegreat wants to merge 1 commit into
FailproofAI:mainfrom
AVPthegreat:fix/custom-policies-policy-params
Open

fix(hooks): pass user-configured policyParams to custom policies (#585)#616
AVPthegreat wants to merge 1 commit into
FailproofAI:mainfrom
AVPthegreat:fix/custom-policies-policy-params

Conversation

@AVPthegreat

@AVPthegreat AVPthegreat commented Jul 28, 2026

Copy link
Copy Markdown

Summary

Fixes #585 by passing user-configured policyParams to custom policies and policies without a pre-defined schema in policy-evaluator.ts.


❌ Root Cause Analysis

In src/hooks/policy-evaluator.ts (lines 94-106):

const schema = POLICY_PARAMS_MAP.get(policy.name);
let ctx: PolicyContext;
if (schema) {
  const userParams = getConfigParamsFor(config, policy.name) ?? {};
  // ...
  ctx = { ...baseCtx, params: resolvedParams };
} else {
  // Custom hooks and policies without schema get empty params
  ctx = { ...baseCtx, params: {} }; // <--- BUG!
}

Why it failed:

  1. POLICY_PARAMS_MAP only contains schemas for built-in policies. For custom policies (e.g. custom/my-policy), schema is undefined.
  2. When schema was undefined, the else branch unconditionally set params: {}.
  3. It never called getConfigParamsFor(config, policy.name), meaning any policyParams: { "custom/my-policy": { maxCount: 10 } } configured in policies-config.json was completely ignored for custom policies.

✅ Fix Details

Updated the else branch in src/hooks/policy-evaluator.ts to query getConfigParamsFor(config, policy.name) when schema is undefined:

} else {
  // Custom hooks and policies without schema get user-configured params if present
  const userParams = getConfigParamsFor(config, policy.name) ?? {};
  ctx = { ...baseCtx, params: userParams };
}

🧪 Unit Tests & Verification

Added unit test in __tests__/hooks/policy-evaluator.test.ts:

it("passes user-configured policyParams to custom policies without schema", async () => {
  let capturedParams: unknown = null;
  registerPolicy("custom/my-policy", "desc", (ctx) => {
    capturedParams = ctx.params;
    return { decision: "allow" };
  }, { events: ["PreToolUse"] });

  const config = {
    enabledPolicies: ["custom/my-policy"],
    policyParams: {
      "custom/my-policy": { maxCount: 10, threshold: 5 },
    },
  };

  await evaluatePolicies("PreToolUse", { tool_name: "Bash" }, undefined, config);
  expect(capturedParams).toEqual({ maxCount: 10, threshold: 5 });
});

Test Results:

  • Ran vitest run __tests__/hooks/policy-evaluator.test.ts
  • Result: ✓ 70 passed (70)

Summary by CodeRabbit

  • Bug Fixes

    • Custom policies without a defined parameter schema now receive their configured policy parameters during evaluation.
    • Policies continue to receive an empty parameter set when no configuration is provided.
  • Tests

    • Added coverage verifying that custom policies receive configured parameters unchanged.

Copilot AI review requested due to automatic review settings July 28, 2026 09:22
@coderabbitai

coderabbitai Bot commented Jul 28, 2026

Copy link
Copy Markdown

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: e3f9ffb9-101e-4a8e-8f98-e4e145932ace

📥 Commits

Reviewing files that changed from the base of the PR and between af74838 and 0d7c9df.

📒 Files selected for processing (2)
  • __tests__/hooks/policy-evaluator.test.ts
  • src/hooks/policy-evaluator.ts

📝 Walkthrough

Walkthrough

evaluatePolicies now forwards configured policyParams to custom policies without parameter schemas, while retaining an empty-object fallback. A Vitest test verifies that the configured values arrive unchanged in ctx.params.

Changes

Custom policy parameter forwarding

Layer / File(s) Summary
Forward configured parameters and verify evaluation
src/hooks/policy-evaluator.ts, __tests__/hooks/policy-evaluator.test.ts
Schema-less policies receive configured parameters through ctx.params, and a test confirms exact forwarding of { maxCount, threshold }.

Estimated code review effort: 2 (Simple) | ~10 minutes

Suggested reviewers: copilot

Poem

A bunny found params tucked out of sight,
And passed them along with a hop of delight.
Custom hooks now see
Their config decree—
No more empty baskets tonight!

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly summarizes the main fix: forwarding user-configured policyParams to custom policies.
Description check ✅ Passed It explains the bug, fix, and test evidence, but it does not follow the template's Type of Change or Checklist sections.
Linked Issues check ✅ Passed The code and test directly address #585 by passing configured policyParams to custom policies without schemas.
Out of Scope Changes check ✅ Passed The changes stay focused on policy parameter forwarding and the corresponding unit test, with no unrelated edits.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.

Warning

There were issues while running some tools. Please review the errors and either fix the tool's configuration or disable the tool if it's a critical failure.

🔧 ESLint

If the error stems from missing dependencies, add them to the package.json file. For unrecoverable errors (e.g., due to private dependencies), disable the tool in the CodeRabbit configuration.

ESLint install timed out. The project may have too many dependencies for the sandbox.


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@hermes-exosphere

Copy link
Copy Markdown
Contributor

Your PR is awaiting review by a reviewer. Till then you can join the Discord for conversation: https://discord.befailproof.ai

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR fixes an evaluation gap in the hook policy system by ensuring custom policies (and any policies without a built-in params schema) receive user-configured policyParams via ctx.params, aligning behavior with user expectations and the existing config surface.

Changes:

  • Updated evaluatePolicies() to pass getConfigParamsFor(config, policy.name) through when a policy has no schema (instead of always {}).
  • Added a unit test verifying that a custom policy without schema receives configured params.

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 1 comment.

File Description
src/hooks/policy-evaluator.ts Passes user-configured params to schema-less/custom policies during evaluation.
tests/hooks/policy-evaluator.test.ts Adds coverage to ensure custom policies without schema receive configured policyParams.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +104 to +106
// Custom hooks and policies without schema get user-configured params if present
const userParams = getConfigParamsFor(config, policy.name) ?? {};
ctx = { ...baseCtx, params: userParams };
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Custom policies silently receive empty ctx.paramspolicyParams config is ignored for them

3 participants