Skip to content

⚡ Bolt: Remove synchronous I/O operations from core logic#102

Merged
iotserver24 merged 1 commit into
mainfrom
bolt/async-fs-ops-10425669300620653950
May 24, 2026
Merged

⚡ Bolt: Remove synchronous I/O operations from core logic#102
iotserver24 merged 1 commit into
mainfrom
bolt/async-fs-ops-10425669300620653950

Conversation

@iotserver24
Copy link
Copy Markdown
Owner

@iotserver24 iotserver24 commented May 24, 2026

💡 What: Replaced synchronous fs.existsSync checks with asynchronous file operations (fs.promises.readFile, fs.promises.access) and structured try/catch error handling across the core package (e.g., agent.ts, memory.ts, auto-memory.ts, permission-store.ts, code-graph.ts).
🎯 Why: Using synchronous file system operations blocks the Node.js event loop, resulting in micro-stutters and decreased responsiveness, particularly during I/O-heavy processes like initialization or loading settings. It also introduces potential Time-of-Check to Time-of-Use (TOCTOU) race conditions.
📊 Impact: Prevents main thread blocking and improves application concurrency.
🔬 Measurement: Run pnpm test and verify that the application initializes without hanging and the tests pass successfully.


PR created automatically by Jules for task 10425669300620653950 started by @iotserver24

Summary by CodeRabbit

  • Refactor

    • Improved file I/O performance by replacing synchronous with asynchronous file operations throughout core modules.
  • Documentation

    • Added guidance on using non-blocking file operations and avoiding race conditions.

Review Change Stack

Replaced `fs.existsSync` with asynchronous file operations (`fs.promises.readFile`, `fs.promises.access`, `fs.promises.mkdir`) wrapped in `try/catch` blocks across the `packages/core` package.

This change prevents blocking the Node.js event loop during initialization or loading operations, improving overall application concurrency and responsiveness.
@google-labs-jules
Copy link
Copy Markdown

👋 Jules, reporting for duty! I'm here to lend a hand with this pull request.

When you start a review, I'll add a 👀 emoji to each comment to let you know I've read it. I'll focus on feedback directed at me and will do my best to stay out of conversations between you and other bots or reviewers to keep the noise down.

I'll push a commit with your requested changes shortly after. Please note there might be a delay between these steps, but rest assured I'm on the job!

For more direct control, you can switch me to Reactive Mode. When this mode is on, I will only act on comments where you specifically mention me with @jules. You can find this option in the Pull Request section of your global Jules UI settings. You can always switch back!

New to Jules? Learn more at jules.google/docs.


For security, I will only act on instructions from the user who triggered this task.

@xibe-review
Copy link
Copy Markdown

xibe-review Bot commented May 24, 2026

Hey @iotserver24! 👋

I'll go through the changes and help you out with an automated review! 🔍

Starting the review now...

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented May 24, 2026

Caution

Review failed

The pull request is closed.

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 6b027ed6-e3d5-4ed1-b8d1-2f5eb87a564a

📥 Commits

Reviewing files that changed from the base of the PR and between e25b3b0 and 395e27c.

📒 Files selected for processing (6)
  • .jules/bolt.md
  • packages/core/src/agent.ts
  • packages/core/src/code-graph.ts
  • packages/core/src/memory.ts
  • packages/core/src/permission-store.ts
  • packages/core/src/utils/auto-memory.ts

📝 Walkthrough

Walkthrough

This PR migrates the core codebase from synchronous filesystem checks (fs.existsSync, fs.readFileSync) to asynchronous alternatives using fs.promises with try...catch error handling. The pattern eliminates blocking I/O and addresses race conditions across agent memory loading, memory initialization, configuration detection, and permission persistence.

Changes

Async filesystem pattern refactoring

Layer / File(s) Summary
Async filesystem pattern guidance
.jules/bolt.md
Documentation added describing the pattern of replacing synchronous filesystem checks with asynchronous fs.promises methods and try/catch blocks, emphasizing avoidance of event-loop blocking and TOCTOU race conditions.
Agent memory async loading
packages/core/src/agent.ts
Agent imports and uses async readFile instead of sync existsSync and readFileSync, removing the explicit file existence check and directly attempting to load .xibecode/memory.md inside try/catch; missing files are silently ignored.
Memory initialization and auto-memory async refactors
packages/core/src/memory.ts, packages/core/src/utils/auto-memory.ts
Neural memory init replaces existsSync with async mkdir and readFile try/catch for directory creation and memory.json loading; auto-memory utilities replace directory existence checks with async access and remove redundant early returns, relying entirely on try/catch for missing file handling.
Configuration detection async refactor
packages/core/src/code-graph.ts
CodeGraph.init() replaces synchronous existsSync check for tsconfig.json with async fs.promises.access wrapped in try/catch, using a boolean flag to drive project initialization branching without altering public behavior.
Permission store async file loading
packages/core/src/permission-store.ts
PermissionStore.load() removes the explicit file existence check and directly reads and parses JSON inside try/catch, returning null on any failure, relying on async fs.promises throughout.

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~12 minutes

Possibly related PRs

  • iotserver24/Xibecode#56: Both PRs update the agent's fallback "Project Memory" loader to read .xibecode/memory.md asynchronously, replacing sync fs.readFileSync/existence checks with fs/promises.readFile + try/catch in the same code path.

Poem

🐰 No more blocks upon the event loop's race,
Async promises now fill this place,
From sync to promises, we gently flow,
Files load gentle, errors we know.
The rabbit hops through async delight! ✨

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch bolt/async-fs-ops-10425669300620653950

Warning

There were issues while running some tools. Please review the errors and either fix the tool's configuration or disable the tool if it's a critical failure.

🔧 ESLint

If the error stems from missing dependencies, add them to the package.json file. For unrecoverable errors (e.g., due to private dependencies), disable the tool in the CodeRabbit configuration.

ESLint skipped: no ESLint configuration detected in root package.json. To enable, add eslint to devDependencies.


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@iotserver24 iotserver24 marked this pull request as ready for review May 24, 2026 17:27
Copilot AI review requested due to automatic review settings May 24, 2026 17:28
@iotserver24 iotserver24 merged commit ea5de4c into main May 24, 2026
5 checks passed
@iotserver24 iotserver24 deleted the bolt/async-fs-ops-10425669300620653950 branch May 24, 2026 17:28
@xibe-review
Copy link
Copy Markdown

xibe-review Bot commented May 24, 2026


🤖 Powered by Xibe AI • Auto-generated
📊 Analysis: 5461 characters analyzed across 6 files
💙 Real-time Analytics📚 Documentation

Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR removes synchronous filesystem existence checks from the core package, replacing them with async fs/promises operations to avoid blocking the Node.js event loop during initialization and memory/permission loading.

Changes:

  • Replaced fs.existsSync gating with async readFile/access + try/catch patterns across core modules.
  • Simplified initialization paths by relying on async ops (e.g., unconditional mkdir({ recursive: true })) and handling ENOENT via exceptions.
  • Updated internal Bolt notes to capture the “avoid sync fs” learning.

Reviewed changes

Copilot reviewed 6 out of 6 changed files in this pull request and generated 3 comments.

Show a summary per file
File Description
packages/core/src/utils/auto-memory.ts Switches project memory directory detection from existsSync to async access/readdir flow.
packages/core/src/permission-store.ts Removes existsSync check and relies on async readFile with error fallback.
packages/core/src/memory.ts Replaces sync existence checks with async mkdir + readFile guarded by ENOENT handling.
packages/core/src/code-graph.ts Replaces existsSync(tsconfig) with async fs.promises.access gating before project creation.
packages/core/src/agent.ts Removes sync fs import and uses async readFile for the memory.md fallback path.
.jules/bolt.md Documents the “remove synchronous file ops” learning/action item.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines 26 to +33
const tsConfigPath = path.join(this.workingDir, 'tsconfig.json');
if (fs.existsSync(tsConfigPath)) {
let hasTsConfig = false;
try {
await fs.promises.access(tsConfigPath);
hasTsConfig = true;
} catch {
hasTsConfig = false;
}
try {
const content = await readFile(fallbackMd, 'utf-8');
this.autoMemoryMarkdownSection = `\n\n## Project Memory\n\n${content.trim()}`;
} catch { /* ignore if not exist */ }
Comment on lines 117 to 121
try {
await access(autoDir);
const names = await readdir(autoDir, { withFileTypes: true });
const mdFiles = names.filter((d) => d.isFile() && d.name.endsWith('.md')).map((d) => join(autoDir, d.name));
for (const fp of mdFiles.slice(0, MAX_AUTO_LOAD_MEMORIES)) {
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants