fix(install): preserve non-array hook entries during uninstall (#1824)
* fix(install): preserve non-array hook entries during uninstall Uninstall filtering returned null for hook entries without a hooks array, silently deleting user-owned entries with unexpected shapes. Return the entry unchanged instead so only GSD hooks are removed. * test(install): add regression test for non-array hook entry preservation (#1825) Fix mirrored filterGsdHooks helper to match production code and add test proving non-array hook entries survive uninstall filtering.
This commit is contained in:
@@ -4432,7 +4432,7 @@ function uninstall(isGlobal, runtime = 'claude') {
|
||||
const before = JSON.stringify(settings.hooks[eventName]);
|
||||
settings.hooks[eventName] = settings.hooks[eventName]
|
||||
.map(entry => {
|
||||
if (!entry.hooks || !Array.isArray(entry.hooks)) return null;
|
||||
if (!entry.hooks || !Array.isArray(entry.hooks)) return entry;
|
||||
// Filter out individual GSD hooks, keep user hooks
|
||||
entry.hooks = entry.hooks.filter(h => !isGsdHookCommand(h.command));
|
||||
return entry.hooks.length > 0 ? entry : null;
|
||||
|
||||
@@ -325,7 +325,7 @@ describe('uninstall settings cleanup preserves user hooks', () => {
|
||||
function filterGsdHooks(entries) {
|
||||
return entries
|
||||
.map(entry => {
|
||||
if (!entry.hooks || !Array.isArray(entry.hooks)) return null;
|
||||
if (!entry.hooks || !Array.isArray(entry.hooks)) return entry;
|
||||
entry.hooks = entry.hooks.filter(h => !isGsdHookCommand(h.command));
|
||||
return entry.hooks.length > 0 ? entry : null;
|
||||
})
|
||||
@@ -372,6 +372,19 @@ describe('uninstall settings cleanup preserves user hooks', () => {
|
||||
assert.strictEqual(result[0].hooks.length, 1, 'user hook should remain');
|
||||
});
|
||||
|
||||
test('non-array hook entries are preserved during uninstall (#1825)', () => {
|
||||
const entries = [
|
||||
{ type: 'custom', command: 'echo hello' },
|
||||
{ matcher: 'Bash', hooks: [{ type: 'command', command: 'node /path/to/gsd-prompt-guard.js' }] },
|
||||
{ url: 'https://example.com/webhook' },
|
||||
];
|
||||
|
||||
const result = filterGsdHooks(JSON.parse(JSON.stringify(entries)));
|
||||
assert.strictEqual(result.length, 2, 'both non-array entries should survive');
|
||||
assert.deepStrictEqual(result[0], { type: 'custom', command: 'echo hello' }, 'first non-array entry preserved');
|
||||
assert.deepStrictEqual(result[1], { url: 'https://example.com/webhook' }, 'second non-array entry preserved');
|
||||
});
|
||||
|
||||
test('all GSD hook names are recognized by isGsdHookCommand', () => {
|
||||
const gsdCommands = [
|
||||
'node /path/gsd-check-update.js',
|
||||
|
||||
Reference in New Issue
Block a user