@gotgenes/pi-permission-system 10.7.0 → 10.7.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -5,6 +5,13 @@ All notable changes to this project will be documented in this file.
5
5
  The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
6
6
  and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
7
 
8
+ ## [10.7.1](https://github.com/gotgenes/pi-packages/compare/pi-permission-system-v10.7.0...pi-permission-system-v10.7.1) (2026-06-09)
9
+
10
+
11
+ ### Bug Fixes
12
+
13
+ * surface full chained command in bash permission prompt ([#333](https://github.com/gotgenes/pi-packages/issues/333)) ([7f448fb](https://github.com/gotgenes/pi-packages/commit/7f448fb6e394bc37f94c98e04332abdcc8528c46))
14
+
8
15
  ## [10.7.0](https://github.com/gotgenes/pi-packages/compare/pi-permission-system-v10.6.0...pi-permission-system-v10.7.0) (2026-06-09)
9
16
 
10
17
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@gotgenes/pi-permission-system",
3
- "version": "10.7.0",
3
+ "version": "10.7.1",
4
4
  "description": "Permission enforcement extension for the Pi coding agent.",
5
5
  "type": "module",
6
6
  "exports": {
@@ -1,3 +1,4 @@
1
+ import { getNonEmptyString, toRecord } from "./common";
1
2
  import { matchQualifier } from "./denial-messages";
2
3
  import type { SkillPromptEntry } from "./skill-prompt-sanitizer";
3
4
  import type { ToolPreviewFormatter } from "./tool-preview-formatter";
@@ -37,12 +38,18 @@ export function formatAskPrompt(
37
38
  const subject = agentName ? `Agent '${agentName}'` : "Current agent";
38
39
 
39
40
  if (result.toolName === "bash") {
41
+ const subCommand = result.command ?? "";
40
42
  const qualifier = matchQualifier(
41
43
  result.matchedPattern,
42
44
  result.commandContext,
43
45
  );
44
46
  const qualifierInfo = qualifier ? ` ${qualifier}` : "";
45
- return `${subject} requested bash command '${result.command ?? ""}'${qualifierInfo}. Allow this command?`;
47
+ const fullCommand = getNonEmptyString(toRecord(input).command);
48
+ const fullCommandInfo =
49
+ fullCommand && fullCommand !== subCommand
50
+ ? ` (full command: '${fullCommand}')`
51
+ : "";
52
+ return `${subject} requested bash command '${subCommand}'${qualifierInfo}${fullCommandInfo}. Allow this command?`;
46
53
  }
47
54
 
48
55
  if ((result.source === "mcp" || result.toolName === "mcp") && result.target) {
@@ -151,6 +151,73 @@ describe("formatAskPrompt", () => {
151
151
  expect(result).toContain("matched 'git *'");
152
152
  });
153
153
 
154
+ test("appends full command when input contains a chain that differs from the sub-command", () => {
155
+ const result = formatAskPrompt(
156
+ toolResult("bash", { command: "rm -rf ." }),
157
+ undefined,
158
+ { command: 'echo "hello" && rm -rf .' },
159
+ makeFormatter(),
160
+ );
161
+ expect(result).toBe(
162
+ `Current agent requested bash command 'rm -rf .' (full command: 'echo "hello" && rm -rf .'). Allow this command?`,
163
+ );
164
+ });
165
+
166
+ test("suppresses full-command suffix when input command matches the sub-command (no chain)", () => {
167
+ const result = formatAskPrompt(
168
+ toolResult("bash", { command: "git push" }),
169
+ undefined,
170
+ { command: "git push" },
171
+ makeFormatter(),
172
+ );
173
+ expect(result).not.toContain("full command:");
174
+ expect(result).toBe(
175
+ "Current agent requested bash command 'git push'. Allow this command?",
176
+ );
177
+ });
178
+
179
+ test("suppresses full-command suffix when input is undefined", () => {
180
+ const result = formatAskPrompt(
181
+ toolResult("bash", { command: "git push" }),
182
+ undefined,
183
+ undefined,
184
+ makeFormatter(),
185
+ );
186
+ expect(result).not.toContain("full command:");
187
+ });
188
+
189
+ test("suppresses full-command suffix when input has no command field", () => {
190
+ const result = formatAskPrompt(
191
+ toolResult("bash", { command: "git push" }),
192
+ undefined,
193
+ { unrelated: "value" },
194
+ makeFormatter(),
195
+ );
196
+ expect(result).not.toContain("full command:");
197
+ });
198
+
199
+ test("suppresses full-command suffix when input command is empty", () => {
200
+ const result = formatAskPrompt(
201
+ toolResult("bash", { command: "git push" }),
202
+ undefined,
203
+ { command: "" },
204
+ makeFormatter(),
205
+ );
206
+ expect(result).not.toContain("full command:");
207
+ });
208
+
209
+ test("places full-command suffix after the qualifier and before the terminal sentence", () => {
210
+ const result = formatAskPrompt(
211
+ toolResult("bash", { command: "rm -rf foo", matchedPattern: "rm *" }),
212
+ undefined,
213
+ { command: "cd /tmp && rm -rf foo" },
214
+ makeFormatter(),
215
+ );
216
+ expect(result).toBe(
217
+ "Current agent requested bash command 'rm -rf foo' (matched 'rm *') (full command: 'cd /tmp && rm -rf foo'). Allow this command?",
218
+ );
219
+ });
220
+
154
221
  test("formats bash prompt with nested execution context", () => {
155
222
  const result = formatAskPrompt(
156
223
  toolResult("bash", {