diff --git a/tests/docs/autonomous-harness-setup.test.js b/tests/docs/autonomous-harness-setup.test.js index 75e8fe855..59d5c53e0 100644 --- a/tests/docs/autonomous-harness-setup.test.js +++ b/tests/docs/autonomous-harness-setup.test.js @@ -10,7 +10,7 @@ const blocks = [...source.matchAll(/```[^\n]*\n([\s\S]*?)```/g)].map(match => ma const checks = [ ['executable examples omit unpublished packages and the invented dispatch endpoint', () => { assert.doesNotMatch(blocks, /@anthropic\/(?:memory|scheduled-tasks|computer-use)-mcp-server/); - assert.doesNotMatch(blocks, /api\.anthropic\.com\/dispatch/); + assert.ok(!blocks.includes('api.anthropic.com/dispatch')); }], ['CLI examples use the working directory and native session scheduling', () => { assert.doesNotMatch(blocks, /--project\b|mcp__scheduled-tasks__/); diff --git a/tests/lib/claude-settings.test.js b/tests/lib/claude-settings.test.js index dfd5d6b37..53caaf4bb 100644 --- a/tests/lib/claude-settings.test.js +++ b/tests/lib/claude-settings.test.js @@ -55,7 +55,7 @@ function assertAtomicParentReplacementRejected(stage) { const victimRoot = path.join(tempDir, 'victim'); const settingsPath = path.join(targetRoot, 'settings.json'); const victimPath = path.join(victimRoot, 'settings.json'); - const originalOpen = fs.openSync; + const originalFsync = fs.fsyncSync; const originalClose = fs.closeSync; const targetContent = '{"target":true}\n'; const victimContent = '{"victim":"preserve"}\n'; @@ -83,28 +83,20 @@ function assertAtomicParentReplacementRejected(stage) { fs.mkdirSync(victimRoot); fs.writeFileSync(settingsPath, targetContent); fs.writeFileSync(victimPath, victimContent); - fs.openSync = function(file, flags, ...args) { - const isTemp = typeof file === 'string' - && path.dirname(path.resolve(file)) === targetRoot - && path.basename(file).startsWith('.settings.json.') && file.endsWith('.tmp'); - if (isTemp) tempBasename = path.basename(file); - if (isTemp && !replaced && stage === 'open') { - // Replace immediately after the temporary descriptor has been created. - const descriptor = originalOpen.call(fs, file, flags, ...args); + fs.fsyncSync = function(descriptor) { + const result = originalFsync.call(fs, descriptor); + const stagedName = fs.readdirSync(targetRoot).find(name => ( + name.startsWith('.settings.json.') && name.endsWith('.tmp') + )); + if (stagedName) { + tempBasename = stagedName; tempDescriptor = descriptor; - try { - replaceParent(); - } catch (error) { - // The writer has not received this handle yet. If Windows refuses - // the directory rename, the fixture must close its own descriptor. - originalClose.call(fs, descriptor); - throw error; - } - return descriptor; + // Exercise replacement while the staging handle is still open. The + // production writer owns the descriptor and closes it on rejection. + // Intercept fsync rather than forwarding arbitrary file-creation flags. + if (!replacementAttempted && stage === 'open') replaceParent(); } - const descriptor = originalOpen.call(fs, file, flags, ...args); - if (isTemp) tempDescriptor = descriptor; - return descriptor; + return result; }; fs.closeSync = function(descriptor) { const result = originalClose.call(fs, descriptor); @@ -134,7 +126,7 @@ function assertAtomicParentReplacementRejected(stage) { assert.strictEqual(fs.readFileSync(path.join(victimRoot, tempBasename), 'utf8'), 'unrelated replacement file'); } } finally { - fs.openSync = originalOpen; + fs.fsyncSync = originalFsync; fs.closeSync = originalClose; fs.rmSync(tempDir, { recursive: true, force: true }); } diff --git a/tests/lib/install-lifecycle.test.js b/tests/lib/install-lifecycle.test.js index fef01bd8a..ab20e54ca 100644 --- a/tests/lib/install-lifecycle.test.js +++ b/tests/lib/install-lifecycle.test.js @@ -3512,8 +3512,13 @@ function runTests() { }); assert.strictEqual(result.results[0].status, 'repaired'); - assert.strictEqual(fs.statSync(settingsPath).mode & 0o777, 0o600); - assert.deepStrictEqual(JSON.parse(fs.readFileSync(settingsPath, 'utf8')).hooks, managedHooks); + const descriptor = fs.openSync(settingsPath, 'r'); + try { + assert.strictEqual(fs.fstatSync(descriptor).mode & 0o777, 0o600); + assert.deepStrictEqual(JSON.parse(fs.readFileSync(descriptor, 'utf8')).hooks, managedHooks); + } finally { + fs.closeSync(descriptor); + } } finally { cleanup(homeDir); cleanup(projectRoot);