mirror of
https://github.com/affaan-m/everything-claude-code.git
synced 2026-04-14 22:13:41 +08:00
fix: allow destructive bash retry after facts presented
Destructive bash gate previously denied every invocation with no isChecked call, creating an infinite deny loop. Now gates per-command on first attempt and allows retry after the model presents the required facts (targets, rollback plan, user instruction). Addresses greptile P1: "Destructive bash gate permanently blocks" Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -184,8 +184,14 @@ function run(rawInput) {
|
|||||||
const command = toolInput.command || '';
|
const command = toolInput.command || '';
|
||||||
|
|
||||||
if (DESTRUCTIVE_BASH.test(command)) {
|
if (DESTRUCTIVE_BASH.test(command)) {
|
||||||
|
// Gate destructive commands on first attempt; allow retry after facts presented
|
||||||
|
const key = '__destructive__' + command.slice(0, 200);
|
||||||
|
if (!isChecked(key)) {
|
||||||
|
markChecked(key);
|
||||||
return denyResult(destructiveBashMsg());
|
return denyResult(destructiveBashMsg());
|
||||||
}
|
}
|
||||||
|
return rawInput; // allow retry after facts presented
|
||||||
|
}
|
||||||
|
|
||||||
if (!isChecked('__bash_session__')) {
|
if (!isChecked('__bash_session__')) {
|
||||||
markChecked('__bash_session__');
|
markChecked('__bash_session__');
|
||||||
|
|||||||
@@ -166,20 +166,34 @@ function runTests() {
|
|||||||
assert.ok(output.hookSpecificOutput.permissionDecisionReason.includes('call this new file'));
|
assert.ok(output.hookSpecificOutput.permissionDecisionReason.includes('call this new file'));
|
||||||
})) passed++; else failed++;
|
})) passed++; else failed++;
|
||||||
|
|
||||||
// --- Test 4: denies destructive Bash ---
|
// --- Test 4: denies destructive Bash, allows retry ---
|
||||||
clearState();
|
clearState();
|
||||||
if (test('denies destructive Bash commands', () => {
|
if (test('denies destructive Bash commands, allows retry after facts presented', () => {
|
||||||
const input = {
|
const input = {
|
||||||
tool_name: 'Bash',
|
tool_name: 'Bash',
|
||||||
tool_input: { command: 'rm -rf /important/data' }
|
tool_input: { command: 'rm -rf /important/data' }
|
||||||
};
|
};
|
||||||
const result = runBashHook(input);
|
|
||||||
assert.strictEqual(result.code, 0, 'exit code should be 0');
|
// First call: should deny
|
||||||
const output = parseOutput(result.stdout);
|
const result1 = runBashHook(input);
|
||||||
assert.ok(output, 'should produce JSON output');
|
assert.strictEqual(result1.code, 0, 'first call exit code should be 0');
|
||||||
assert.strictEqual(output.hookSpecificOutput.permissionDecision, 'deny');
|
const output1 = parseOutput(result1.stdout);
|
||||||
assert.ok(output.hookSpecificOutput.permissionDecisionReason.includes('Destructive'));
|
assert.ok(output1, 'first call should produce JSON output');
|
||||||
assert.ok(output.hookSpecificOutput.permissionDecisionReason.includes('rollback'));
|
assert.strictEqual(output1.hookSpecificOutput.permissionDecision, 'deny');
|
||||||
|
assert.ok(output1.hookSpecificOutput.permissionDecisionReason.includes('Destructive'));
|
||||||
|
assert.ok(output1.hookSpecificOutput.permissionDecisionReason.includes('rollback'));
|
||||||
|
|
||||||
|
// Second call (retry after facts presented): should allow
|
||||||
|
const result2 = runBashHook(input);
|
||||||
|
assert.strictEqual(result2.code, 0, 'second call exit code should be 0');
|
||||||
|
const output2 = parseOutput(result2.stdout);
|
||||||
|
assert.ok(output2, 'second call should produce valid JSON output');
|
||||||
|
if (output2.hookSpecificOutput) {
|
||||||
|
assert.notStrictEqual(output2.hookSpecificOutput.permissionDecision, 'deny',
|
||||||
|
'should not deny destructive bash retry after facts presented');
|
||||||
|
} else {
|
||||||
|
assert.strictEqual(output2.tool_name, 'Bash', 'pass-through should preserve input');
|
||||||
|
}
|
||||||
})) passed++; else failed++;
|
})) passed++; else failed++;
|
||||||
|
|
||||||
// --- Test 5: denies first routine Bash, allows second ---
|
// --- Test 5: denies first routine Bash, allows second ---
|
||||||
|
|||||||
Reference in New Issue
Block a user