From 0ebba9eba10c78f4c14e104d92e9ba97c10da7eb Mon Sep 17 00:00:00 2001 From: YeonGyu-Kim Date: Wed, 20 May 2026 14:35:11 +0900 Subject: [PATCH] fix(rules-injector): retry storage writes after cleanup race The full Bun suite can remove the shared rules-injector storage directory between a parent-directory check and the file write. Save operations now create the directory immediately before writing and retry once if ENOENT still wins the race. Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent) Co-authored-by: Sisyphus --- src/hooks/rules-injector/storage.ts | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/src/hooks/rules-injector/storage.ts b/src/hooks/rules-injector/storage.ts index fc01a591d..a190b7232 100644 --- a/src/hooks/rules-injector/storage.ts +++ b/src/hooks/rules-injector/storage.ts @@ -37,10 +37,6 @@ export function saveInjectedRules( sessionID: string, data: { contentHashes: Set; realPaths: Set } ): void { - if (!existsSync(RULES_INJECTOR_STORAGE)) { - mkdirSync(RULES_INJECTOR_STORAGE, { recursive: true }); - } - const storageData: InjectedRulesData = { sessionID, injectedHashes: [...data.contentHashes], @@ -48,7 +44,16 @@ export function saveInjectedRules( updatedAt: Date.now(), }; - writeFileSync(getStoragePath(sessionID), JSON.stringify(storageData, null, 2)); + mkdirSync(RULES_INJECTOR_STORAGE, { recursive: true }); + try { + writeFileSync(getStoragePath(sessionID), JSON.stringify(storageData, null, 2)); + } catch (error) { + if (!(error instanceof Error) || !("code" in error) || error.code !== "ENOENT") { + throw error; + } + mkdirSync(RULES_INJECTOR_STORAGE, { recursive: true }); + writeFileSync(getStoragePath(sessionID), JSON.stringify(storageData, null, 2)); + } } export function clearInjectedRules(sessionID: string): void {