fix: Strip no-op cd-to-cwd prefix before permission checks
Agent frequently prepends "cd <cwd> && " to commands, which defeats
auto-allow rules since the wrapped command no longer matches the "jj "
prefix check.

Assisted-by: Claude Opus 4 via pi
change nsvospxxvvulsrqvlmmwymvxsmpnvslw
commit 841b0afb38ee68d70e40d33d1aecb72eaaf1addf
author Alpha Chen <alpha@kejadlen.dev>
date
parent rmksupxw
diff --git a/.pi/agent/extensions/permission-gate.ts b/.pi/agent/extensions/permission-gate.ts
index 091129f2..afbd7166 100644
--- a/.pi/agent/extensions/permission-gate.ts
+++ b/.pi/agent/extensions/permission-gate.ts
@@ -58,6 +58,19 @@ function isInSkillsDirectory(filePath: string, ctx: ExtensionContext): boolean {
   return false;
 }
 
+/**
+ * Strip a leading `cd <cwd> && ` or `cd <cwd> ; ` prefix from a command.
+ * The agent often wraps commands this way, which is a no-op but obscures the
+ * real command from permission checks.
+ */
+function stripCdToCwd(cmd: string, cwd: string): string {
+  const prefix = `cd ${cwd} && `;
+  if (cmd.startsWith(prefix)) return cmd.slice(prefix.length);
+  const prefixSemi = `cd ${cwd} ; `;
+  if (cmd.startsWith(prefixSemi)) return cmd.slice(prefixSemi.length);
+  return cmd;
+}
+
 function isAllowed(toolName: string, input: Record<string, unknown>, ctx: ExtensionContext): boolean {
   if (toolName === "read") {
     const filePath = path.resolve(ctx.cwd, String(input.path ?? ""));
@@ -65,7 +78,7 @@ function isAllowed(toolName: string, input: Record<string, unknown>, ctx: Extens
   }
 
   if (toolName === "bash") {
-    const cmd = String(input.command ?? "").trimStart();
+    const cmd = stripCdToCwd(String(input.command ?? "").trimStart(), ctx.cwd);
     if (cmd.startsWith("jj ")) {
       const subcommand = cmd.slice(3).trimStart().split(/\s/)[0];
       return ALLOWED_JJ_SUBCOMMANDS.includes(subcommand);