Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Evaluate Wayfinder-shaped Bash command canonicalization #78
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Uh oh!
There was an error while loading. Please reload this page.
Evaluate Wayfinder-shaped Bash command canonicalization #78
Changes from all commits
5923d6c4d8618aa264d5eFile filter
Filter by extension
Conversations
Uh oh!
There was an error while loading. Please reload this page.
Jump to
Uh oh!
There was an error while loading. Please reload this page.
There are no files selected for viewing
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
issue (bug_risk): Avoid using File.cwd!/0 when :cwd is nil but :repo_root is provided to prevent mis-detecting redundant
git -C.In
equivalent_context_path?/3, whencwdis nil butrepo_rootis set,expand_path/2still falls back toFile.cwd!/0. This makes the OS working directory affect whethergit -Cis seen as redundant and can cause us to strip a-Cthat should change context from the agent’s perspective.Instead of using
File.cwd!/0here, either treatpathas non-equivalent whencwdis nil, or require explicitcwd/repo_rootvalues for these checks so equivalence is based only on explicit context, not ambient process state.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Using
File.cwd!()can raise aFile.Errorexception if the current working directory is inaccessible or has been deleted. Sincecanonicalize/2is used for preflight tool-call canonicalization, an unhandled exception here could crash the mediation pipeline.Additionally, if we preserve quotes in
do_tokenize/4, we need to strip quotes from thepathbefore checking for equivalence. We can add a helperstrip_quotes/1here.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The
dynamic_shell_variable?/1check can be bypassed by using the standard Bash syntax${VAR}instead of$VAR. Since the regex~r/(^|[^\$])\$[_A-Za-z][_A-Za-z0-9]*/expects a letter or underscore immediately after the$, it fails to match${VAR}.If bypassed, a command like
FILES=$(rg --files); wc -l ${FILES}will be split into["FILES=$(rg --files)", "wc -l ${FILES}"]and marked as"rewritten". When executed as separate commands, the variable state is lost, completely breaking the command.Additionally, the regex matches escaped variables like
\$VARbecause[^\$]matches the backslash\.Consider using a lookbehind to avoid matching escaped dollar signs, and support both
$VARand${VAR}formats.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Splitting
&&chains into a list of independent commands loses the conditional execution semantics of Bash. In Bash,cmd1 && cmd2ensurescmd2only runs ifcmd1succeeds. If these are split and executed sequentially by the caller without checking the exit status of the previous command, it can lead to dangerous behavior (for example,cd /safe/dir && rm -rf *would runrm -rf *in the current directory if thecdfailed).Consider either keeping
&&chains as a single command (or marking them asrepairif they cannot be safely canonicalized together), or returning structured metadata indicating that the commands must be executed conditionally.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In Bash, backslashes inside single quotes (
'...') have no special meaning and do not act as escape characters. However,do_split_top_level/4handles backslashes regardless of the currentmode. This causes backslashes inside single quotes to incorrectly escape the following character (e.g., escaping a single quote, which is impossible in standard Bash single quotes).We should restrict the backslash clause to only match when
modeis:normalor:double_quote.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In Bash, backslashes inside single quotes (
'...') have no special meaning and do not act as escape characters. However,do_tokenize/4handles backslashes regardless of the currentmode. This causes backslashes inside single quotes to incorrectly escape the following character (e.g., escaping a single quote, which is impossible in standard Bash single quotes).We should restrict the backslash clause to only match when
modeis:normalor:double_quote.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The tokenizer currently strips single and double quotes from all tokens during the tokenization phase. When a command is reconstructed (e.g., in
canonicalize_git_c/5usingEnum.join(["git" | rest], " ")), the original quotes are completely lost.For example,
git -C /workspace/example-repo commit -m 'hello world'will be canonicalized togit commit -m hello world. In Bash, this is a major semantic change becauseworldis no longer part of the commit message and is instead treated as a separate argument.To fix this, the tokenizer should preserve quotes for all tokens, and the path comparison logic should strip quotes only from the
pathargument before checking for equivalence.Uh oh!
There was an error while loading. Please reload this page.