Skip to content

fix(brain-repo): exclude editor and tool config dirs from mirror#83

Open
mt-alarcon wants to merge 1 commit into
evolution-foundation:mainfrom
mt-alarcon:fix/brain-repo-exclude-editor-config-dirs
Open

fix(brain-repo): exclude editor and tool config dirs from mirror#83
mt-alarcon wants to merge 1 commit into
evolution-foundation:mainfrom
mt-alarcon:fix/brain-repo-exclude-editor-config-dirs

Conversation

@mt-alarcon
Copy link
Copy Markdown

@mt-alarcon mt-alarcon commented May 14, 2026

Summary

_EXCLUDE_DIR_NAMES in dashboard/backend/brain_repo/job_runner.py already excludes language and toolchain caches (node_modules, __pycache__, .venv, dist, build, etc.) but does not exclude config directories created by editors and note-taking apps when the user opens a watched path as a workspace/vault. Those directories are per-machine UI state and must not propagate via the brain repo.

Adds four entries to the set:

Path Created by Why exclude
.obsidian/ Obsidian (e.g. opening memory/ as a vault) workspace.json rewritten on every panel/tab change; plugin enablement is per-machine
.trash/ Obsidian + a few editors User-deleted notes pre-purge; syncing resurrects deletions on other machines
.vscode/ VS Code workspace settings Personal launch configs / breakpoints; project-shared bits belong in repo elsewhere
.idea/ JetBrains IDEs (PyCharm, IntelliJ, WebStorm, …) Same rationale as .vscode

How we discovered it

Opened memory/ as an Obsidian vault on a production install (MTA, 2026-05-14). .obsidian/ got created with app.json, appearance.json, core-plugins.json, workspace.json. Without this fix, the next file watcher tick mirrors the entire .obsidian/ directory into the brain repo and then commits + pushes — adding noise to every operator's local copy, churning workspace.json on every panel resize, and (in the .trash/ case) potentially undoing user deletions.

The fix is a defensive widening of the existing exclude set — same mechanism, same ignore callback, no API or schema change.

Test plan

  • Empirical validation — opened the brain memory/ directory as an Obsidian vault on MTA install. Touched a sentinel file (echo ... > memory/.brain-repo-obsidian-test.md) to force the watcher's 30 s debounce. After 41 s:
    • Sentinel file present in brain_repo_dir/memory/
    • .obsidian/ absent from brain_repo_dir/memory/
    • auto: file watcher sync commit pushed to remote ✓
  • No-regression — pre-existing exclusions (.git, __pycache__, node_modules, .venv, etc.) still trip the same ignore callback. Adding entries to a set strictly widens exclusion; it cannot break existing skips.
  • No API change, no migration — pure defensive addition to a defaults set.

Notes for reviewers

  • The four entries are directory names, not paths. They match anywhere in the watched tree (the ignore callback walks names per visited dir). That's the correct behavior for these tools — they always create their config dir directly inside the workspace root the user opened.
  • Non-blocking nit: a future PR could add .zed/, .fleet/, .cursor/ for completeness. Held off here to keep the diff scoped to the editors most reviewers are likely to actually have installed; trivial follow-up if anyone wants them.
  • Companion fix for the same surface: fix(brain-repo): watcher must observe install_dir, not brain_repo_dir #81 (`watcher.py` was observing brain_repo_dir instead of install_dir). That fix made watcher events actually fire; this fix keeps the resulting copytree from copying garbage that the events now correctly surface.

Summary by Sourcery

Bug Fixes:

  • Exclude Obsidian, VS Code, JetBrains, and similar per-machine config directories from the brain repo mirror to avoid syncing local UI state and trash across machines.

@sourcery-ai
Copy link
Copy Markdown

sourcery-ai Bot commented May 14, 2026

Reviewer's guide (collapsed on small PRs)

Reviewer's Guide

Expands the brain repo mirror's directory exclusion set to ignore per-machine editor and note-taking config directories so they are not mirrored, committed, or pushed, without changing any APIs or logic beyond the ignore list contents.

Flow diagram for updated brain repo mirror directory exclusion

flowchart TD
    A[Filesystem change in watched path] --> B[File watcher event]
    B --> C[Mirror job_runner starts]
    C --> D[Walk directory tree]
    D --> E[Check dir_name in _EXCLUDE_DIR_NAMES]
    E -->|Yes: .obsidian / .trash / .vscode / .idea| F[Skip directory and contents]
    E -->|No| G[Include in mirror copy]
    F --> H[Commit and push mirrored changes]
    G --> H[Commit and push mirrored changes]
Loading

File-Level Changes

Change Details Files
Widen the brain repo mirror's exclude-dir name set to skip per-machine editor and tool config directories during sync.
  • Extend the existing _EXCLUDE_DIR_NAMES set with four additional directory names used for local editor and note-taking configuration
  • .obsidian
  • .trash
  • .vscode
  • .idea
  • Document in-line that these directories contain local UI state and should not be propagated via the brain repo
dashboard/backend/brain_repo/job_runner.py

Tips and commands

Interacting with Sourcery

  • Trigger a new review: Comment @sourcery-ai review on the pull request.
  • Continue discussions: Reply directly to Sourcery's review comments.
  • Generate a GitHub issue from a review comment: Ask Sourcery to create an
    issue from a review comment by replying to it. You can also reply to a
    review comment with @sourcery-ai issue to create an issue from it.
  • Generate a pull request title: Write @sourcery-ai anywhere in the pull
    request title to generate a title at any time. You can also comment
    @sourcery-ai title on the pull request to (re-)generate the title at any time.
  • Generate a pull request summary: Write @sourcery-ai summary anywhere in
    the pull request body to generate a PR summary at any time exactly where you
    want it. You can also comment @sourcery-ai summary on the pull request to
    (re-)generate the summary at any time.
  • Generate reviewer's guide: Comment @sourcery-ai guide on the pull
    request to (re-)generate the reviewer's guide at any time.
  • Resolve all Sourcery comments: Comment @sourcery-ai resolve on the
    pull request to resolve all Sourcery comments. Useful if you've already
    addressed all the comments and don't want to see them anymore.
  • Dismiss all Sourcery reviews: Comment @sourcery-ai dismiss on the pull
    request to dismiss all existing Sourcery reviews. Especially useful if you
    want to start fresh with a new review - don't forget to comment
    @sourcery-ai review to trigger a new review!

Customizing Your Experience

Access your dashboard to:

  • Enable or disable review features such as the Sourcery-generated pull request
    summary, the reviewer's guide, and others.
  • Change the review language.
  • Add, remove or edit custom review instructions.
  • Adjust other review settings.

Getting Help

Copy link
Copy Markdown

@sourcery-ai sourcery-ai Bot left a comment

Choose a reason for hiding this comment

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

Hey - I've found 1 issue

Prompt for AI Agents
Please address the comments from this code review:

## Individual Comments

### Comment 1
<location path="dashboard/backend/brain_repo/job_runner.py" line_range="197-200" />
<code_context>
+    # workspace in VS Code writes .vscode/; JetBrains writes .idea/). The content
+    # is local UI state (open tabs, window geometry, plugin enablement) that
+    # should never propagate across machines via the brain repo.
+    ".obsidian",
+    ".trash",
+    ".vscode",
+    ".idea",
 }

</code_context>
<issue_to_address>
**question (bug_risk):** Consider whether `.trash` is too generic and might hide intentional user content.

The tool-specific entries seem fine, but `.trash` is generic and could plausibly be used as a legitimate, tracked directory. Consider restricting this to known application trash locations or a more specific pattern (e.g., under certain config paths) to avoid silently ignoring real repository content.
</issue_to_address>

Sourcery is free for open source - if you like our reviews please consider sharing them ✨
Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.

Comment thread dashboard/backend/brain_repo/job_runner.py
`_EXCLUDE_DIR_NAMES` in `dashboard/backend/brain_repo/job_runner.py` already
excludes language and toolchain caches (node_modules, __pycache__, .venv,
dist, build, etc.). It does NOT exclude the config directories that
editors / note-taking apps drop into a path when the user opens that path
as a workspace or vault. Those directories are per-machine UI state and
must not propagate via the brain repo.

Affected paths added:

  - `.obsidian/` — created when the user opens any watched directory
    (e.g. `memory/`) as an Obsidian vault. Contains workspace.json
    (open tabs, panel layout), per-vault enabled plugins, hotkeys, and
    appearance overrides. None of this transfers meaningfully across
    machines: opening the same vault on a second machine creates a
    fresh `.obsidian/` regardless. Propagating it just produces noisy
    diffs (workspace.json is rewritten on every panel/tab change).

  - `.vscode/` — VS Code workspace settings. Two sub-cases: (a) shared
    project settings that belong in the repo and should be committed
    explicitly elsewhere; (b) personal launch configs / debug breakpoints
    that should never leak. Default-excluding follows the more common
    project pattern (.vscode is almost always gitignored).

  - `.idea/` — JetBrains IDEs (PyCharm, IntelliJ, WebStorm, etc.).
    Same rationale as .vscode — almost always gitignored, occasionally
    explicitly checked-in pieces, but never appropriate for a content
    mirror.

Sourcery review applied (2026-05-14):
  - Dropped `.trash` from the original draft. Sourcery flagged it as
    "too generic — could plausibly be legitimate user content the
    mirror would silently hide." Each remaining entry is unambiguously
    tied to a single application (folder name uniquely identifies
    Obsidian / VS Code / JetBrains).

## Why this matters

The brain repo file watcher (and the manual sync_force path) calls
`shutil.copytree(src, dst, ignore=build_ignore_callback(...))`. The
ignore callback walks `_EXCLUDE_DIR_NAMES` per visited directory.
Adding these three entries blocks the mirror from copying:

  - Megabytes of per-machine UI state on every dispatch
  - Editor lock files that change on every focus/blur
  - Plugin state that varies between operator boxes

## Test plan

- [x] Empirical (MTA install, 2026-05-14): opened `memory/` as an Obsidian
  vault — `.obsidian/` created with `app.json`, `appearance.json`,
  `core-plugins.json`, `workspace.json`. Touched a sentinel file in
  `memory/` to force the watcher's 30s debounce. After 41 seconds,
  observed: sentinel file present in the brain repo destination,
  `.obsidian/` ABSENT (no leakage). Mirror behaved as intended.
- [x] No-regression check: pre-existing exclusions (`.git`, `__pycache__`,
  `node_modules`, `.venv`, etc.) still trip the ignore callback exactly
  the same way — adding entries to a `set` only widens the exclusion,
  it can't break existing skips.
- [x] No API change, no config schema change, no migration. Pure
  defensive addition to a defaults set.

## Notes for reviewers

- The three directory names are *names*, not paths. They match anywhere
  in the watched tree (the ignore callback walks names per visited dir).
  That's the correct behavior for these tools — they always create their
  config dir directly inside the workspace root the user opened.
- Personal preference (mine, not blocking): could add `.zed/`, `.fleet/`,
  `.cursor/` for completeness. Held off to keep the diff scoped to
  editors that someone reading this PR is most likely to actually have
  installed. Easy follow-up if anyone wants them.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
@mt-alarcon
Copy link
Copy Markdown
Author

@sourcery-ai review

Addressed in $(cd /tmp/evo-nexus-pr-brain-exclude-editor-dirs && git rev-parse --short HEAD):

Dropped .trash from the exclude set. You're right — it's the only name in the original draft that isn't unambiguously tied to a single application (Obsidian, VS Code, JetBrains all create their config dir under a distinctive name; .trash is generic enough that an operator could plausibly have a .trash/ directory of legitimate content the mirror would silently hide). Users who want Obsidian deletions purged immediately can configure that in Obsidian itself (Settings → Files & Links → Deleted files → 'Permanently delete'); we don't need a defaults-level decision for them.

The other three entries stay — folder name uniquely identifies the originating app, and the mirror noise / per-machine churn is real (validated empirically with Obsidian on the MTA install).

@mt-alarcon mt-alarcon force-pushed the fix/brain-repo-exclude-editor-config-dirs branch from 53e19cf to 0c9d1bd Compare May 14, 2026 14:46
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.

1 participant