Skip to content

feat(tui): apply file ask rules at runtime#3379

Open
greyfreedom wants to merge 1 commit into
Hmbown:mainfrom
greyfreedom:feat/permissions-file-ask-runtime
Open

feat(tui): apply file ask rules at runtime#3379
greyfreedom wants to merge 1 commit into
Hmbown:mainfrom
greyfreedom:feat/permissions-file-ask-runtime

Conversation

@greyfreedom

Copy link
Copy Markdown
Contributor

Summary

Wire ask-only permissions.toml file-path rules into the TUI runtime approval path.

Scope

  • Evaluate typed ask rules for file-oriented tools during model tool planning.
  • Force an approval prompt when a matching file-path ask rule is hit under approval modes that can ask.
  • Reject the tool call when the same ask rule matches under AskForApproval::Never.
  • Preserve existing allow/deny command-prefix behavior and existing tool approval defaults.
  • Cover matching, Never-mode blocking, and unmatched-path behavior with engine tests.
  • Update docs/TOOL_SURFACE.md to document explicit file-path ask-rule runtime handling.

Not in this slice

  • Typed allow/deny rules.
  • Glob expansion or broader path pattern matching.
  • Approval UI persistence for file rules.
  • Importing the full permission DSL from the earlier reference branch.
  • Changing session approval, command-prefix trust, or existing write-tool approval defaults.

Builds on

  • The landed ask-only permissions.toml schema/loading work.
  • The landed runtime support for exec_shell ask rules.
  • The landed approval UI persistence for exec_shell ask rules.

Issues

Refs #1186 (partial)
Refs #2242 (partial)

Validation

  • cargo fmt --all -- --check
  • cargo check -p codewhale-tui --bin codewhale-tui
  • cargo test -p codewhale-tui --bin codewhale-tui ask_rule_decision -- --nocapture
  • cargo test -p codewhale-tui --bin codewhale-tui ask_rule -- --nocapture
  • git diff --check

Wire typed ask-only permissions.toml file-path rules into the TUI tool approval planning path. Matching file ask rules now force approval when approval is available and block under AskForApproval::Never, while preserving existing allow/deny command behavior.

This is a narrow follow-up slice from the persistent permissions reference branch: it does not add typed allow/deny, glob expansion, or approval UI persistence for file rules.
@greyfreedom greyfreedom requested a review from Hmbown as a code owner June 22, 2026 04:34

@greptile-apps greptile-apps Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Your free trial has ended. If you'd like to continue receiving code reviews, you can add a payment method here.

@github-actions

Copy link
Copy Markdown

Thanks @greyfreedom for taking the time to contribute.

This repository is observing a maintainer-managed PR intake gate in dry-run mode, so this pull request is staying open. This note helps maintainers prepare the allowlist before any enforcement is considered.

Please read CONTRIBUTING.md for the expected contribution shape. A maintainer can grant recurring PR access by commenting /lgtm on a pull request.

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Code Review

This pull request generalizes the shell execution ask-rule decision logic into a broader tool ask-rule decision framework, extending support to file-based tools (such as read_file, write_file, apply_patch, etc.). It renames ExecShellAskRuleDecision to ToolAskRuleDecision and implements file_tool_ask_rule_decision to evaluate permissions for file operations. Feedback suggests optimizing the turn loop by wrapping the evaluation of ask rules inside a check for blocked_error.is_none(), preventing unnecessary and potentially expensive computations when a tool is already blocked.

Important

The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.

Comment on lines +1585 to 1603
let ask_rule_decision = exec_shell_ask_rule_decision(
&self.config,
&tool_name,
&tool_input,
&self.session.workspace,
self.session.approval_mode,
)
.or_else(|| {
file_tool_ask_rule_decision(
&self.config,
&tool_name,
&tool_input,
&self.session.workspace,
self.session.approval_mode,
)
});
if blocked_error.is_none()
&& let Some(decision) = ask_rule_decision
{

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

medium

Evaluating the ask rules (exec_shell_ask_rule_decision and file_tool_ask_rule_decision) can be expensive, especially for apply_patch which parses unified diffs. We should only perform these checks if blocked_error is None to avoid unnecessary work when the tool is already blocked.

                if blocked_error.is_none() {
                    let ask_rule_decision = exec_shell_ask_rule_decision(
                        &self.config,
                        &tool_name,
                        &tool_input,
                        &self.session.workspace,
                        self.session.approval_mode,
                    )
                    .or_else(|| {
                        file_tool_ask_rule_decision(
                            &self.config,
                            &tool_name,
                            &tool_input,
                            &self.session.workspace,
                            self.session.approval_mode,
                        )
                    });
                    if let Some(decision) = ask_rule_decision {
                        match decision {
                            ToolAskRuleDecision::Prompt(reason) => {
                                approval_required = true;
                                approval_description = reason;
                                approval_force_prompt = true;
                            }
                            ToolAskRuleDecision::Block(reason) => {
                                approval_required = false;
                                approval_force_prompt = false;
                                blocked_error = Some(ToolError::permission_denied(reason));
                            }
                        }
                    }
                }

@Hmbown

Hmbown commented Jun 22, 2026

Copy link
Copy Markdown
Owner

Thanks @greyfreedom — I carried this into the v0.8.64 integration branch with attribution:

  • ad1c5a6 feat(tui): apply file ask rules at runtime

I folded in the review note so file/shell ask-rule evaluation is skipped once a tool is already blocked by earlier planning. Verified with:

  • cargo fmt --all
  • cargo test -p codewhale-tui --bin codewhale-tui --locked file_ask_rule_decision
  • cargo test -p codewhale-tui --bin codewhale-tui --locked exec_shell_ask_rule_decision
  • RUSTFLAGS=-Dwarnings cargo check -p codewhale-tui --bin codewhale-tui --locked
  • git diff --check HEAD~2..HEAD
  • python3 scripts/check-coauthor-trailers.py --author-map .github/AUTHOR_MAP --range HEAD~2..HEAD --check-authors

This is a good fit for the v0.8.64 hardening lane.

@Hmbown

Hmbown commented Jun 22, 2026

Copy link
Copy Markdown
Owner

Thank you @greyfreedom — file-ask-rule application at runtime landed in the v0.8.64 release branch (file_tool_ask_rule_decision + exec_shell_ask_rule_decision in crates/tui/src/core/engine.rs, applied in the turn loop). Your PR helped validate the design. Appreciate it!

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.

2 participants