Hello! 👋 This is a small, self-contained fix with a genuinely fun story behind it
If you'd like a first contribution to Neo that touches something real without needing deep framework context, this is a good one. It is a three-line change plus a test, in a well-covered file, and the bug is easy to see once you look at it.
The story
Neo's agents work in multiple checkouts on one machine. A script hydrates each one by symlinking the shared .neo-ai-data/ substrate directories — sqlite/, logs/, and so on — from a canonical checkout, so every seat reads the same data.
It decides what to link by enumerating every child of the canonical directory and linking all of them except an explicit blocklist. That "blocklist, not allowlist" choice is deliberate and correct: it means a new substrate directory is shared automatically, instead of being silently orphaned because someone forgot to add it to a list.
The catch: macOS Finder writes a .DS_Store file into any directory you browse. So one appeared in the canonical .neo-ai-data/, the enumeration found it, and — being neither on the blocklist nor recognisable as anything special — it got hydrated as shared substrate.
Measured on a live machine today:
.DS_Store classified as: alreadyLinked
-> resolved: <canonical>/.neo-ai-data/.DS_Store
alreadyLinked is the "properly shared, working as intended" bucket. Two of three agent checkouts carry a symlink to it. Ask the tooling "what is in the shared data plane?" and a Finder artifact is part of the answer.
It is harmless in itself — but it pollutes the inventory that a current architecture decision is being made from (@neo-opus-grace is filling a cost table from exactly this data on #15800), and the next one could be an editor swap file or a crash dump instead.
The Problem
symlinkDataDir() in ai/scripts/migrations/bootstrapWorktree.mjs enumerates .neo-ai-data/ children and classifies each as linkable substrate unless it appears in DATA_SUBDIRS_BLOCKLIST (currently ['concepts', 'orchestrator-daemon', 'embed-daemon']) or the read-alias sets.
Dot-entries are never managed substrate. Every real substrate leaf is an ordinary named directory. OS and tool artifacts — .DS_Store, .Spotlight-V100, editor lock files — are all dot-prefixed, and there is currently nothing that excludes them as a class.
Note the repo already declares this file as non-content: .gitignore carries .DS_Store. Two declarations disagree — git says "never content", the hydration says "shared substrate".
The Fix
Skip dot-prefixed entries in the enumeration, as a class rather than adding .DS_Store to the blocklist as an instance. Adding the one name would leave .Spotlight-V100 and the next artifact equally welcome — and the blocklist's job is naming deliberately seat-local substrate, not filtering junk.
Roughly (in symlinkDataDir, where children are classified):
if (name.startsWith('.')) continue; Please add a short comment saying why, in the style of the surrounding code — this file explains its reasoning heavily and a future reader should not have to rediscover the .DS_Store story.
Acceptance Criteria
Getting started
- The file:
ai/scripts/migrations/bootstrapWorktree.mjs — look for symlinkDataDir and DATA_SUBDIRS_BLOCKLIST.
- The tests:
test/playwright/unit/ai/scripts/migrations/bootstrapWorktree.spec.mjs, the #10432 symlinkDataDir describe block. They use temp dirs as fake checkouts, so nothing on your machine is touched.
- Run just this spec:
npm run test-unit -- test/playwright/unit/ai/scripts/migrations/bootstrapWorktree.spec.mjs
- Please make the test fail first against the unfixed code — that is how we know it pins the behaviour rather than the implementation. If it passes before your change, it is testing something else.
Questions welcome on the issue. There is no rush and no wrong question.
Out of Scope
- Removing the existing
.DS_Store from the canonical directory (housekeeping, and it will simply stop being linked once this lands).
- Any change to
DATA_SUBDIRS_BLOCKLIST's contents or to the reconcile reporting.
- The symlink-escape and mount-topology questions on #15800 — unrelated, and being handled there.
Related
- #15791 / PR #15794 — where the reconcile surfaced this, recorded then as an out-of-scope gap.
- #15800 — the placement election consuming this inventory; @neo-opus-grace's measurement is what confirmed the leaf is live rather than theoretical.
Decision Record impact: none.
Live latest-open sweep: checked open issues at 2026-07-24T18:02Z; no equivalent found.
Retrieval Hint: query_raw_memories("DS_Store hydrated as substrate dot-entry blocklist neo-ai-data")
Hello! 👋 This is a small, self-contained fix with a genuinely fun story behind it
If you'd like a first contribution to Neo that touches something real without needing deep framework context, this is a good one. It is a three-line change plus a test, in a well-covered file, and the bug is easy to see once you look at it.
The story
Neo's agents work in multiple checkouts on one machine. A script hydrates each one by symlinking the shared
.neo-ai-data/substrate directories —sqlite/,logs/, and so on — from a canonical checkout, so every seat reads the same data.It decides what to link by enumerating every child of the canonical directory and linking all of them except an explicit blocklist. That "blocklist, not allowlist" choice is deliberate and correct: it means a new substrate directory is shared automatically, instead of being silently orphaned because someone forgot to add it to a list.
The catch: macOS Finder writes a
.DS_Storefile into any directory you browse. So one appeared in the canonical.neo-ai-data/, the enumeration found it, and — being neither on the blocklist nor recognisable as anything special — it got hydrated as shared substrate.Measured on a live machine today:
alreadyLinkedis the "properly shared, working as intended" bucket. Two of three agent checkouts carry a symlink to it. Ask the tooling "what is in the shared data plane?" and a Finder artifact is part of the answer.It is harmless in itself — but it pollutes the inventory that a current architecture decision is being made from (@neo-opus-grace is filling a cost table from exactly this data on #15800), and the next one could be an editor swap file or a crash dump instead.
The Problem
symlinkDataDir()inai/scripts/migrations/bootstrapWorktree.mjsenumerates.neo-ai-data/children and classifies each as linkable substrate unless it appears inDATA_SUBDIRS_BLOCKLIST(currently['concepts', 'orchestrator-daemon', 'embed-daemon']) or the read-alias sets.Dot-entries are never managed substrate. Every real substrate leaf is an ordinary named directory. OS and tool artifacts —
.DS_Store,.Spotlight-V100, editor lock files — are all dot-prefixed, and there is currently nothing that excludes them as a class.Note the repo already declares this file as non-content:
.gitignorecarries.DS_Store. Two declarations disagree — git says "never content", the hydration says "shared substrate".The Fix
Skip dot-prefixed entries in the enumeration, as a class rather than adding
.DS_Storeto the blocklist as an instance. Adding the one name would leave.Spotlight-V100and the next artifact equally welcome — and the blocklist's job is naming deliberately seat-local substrate, not filtering junk.Roughly (in
symlinkDataDir, where children are classified):if (name.startsWith('.')) continue; // dot-entries are OS/tool artifacts, never managed substratePlease add a short comment saying why, in the style of the surrounding code — this file explains its reasoning heavily and a future reader should not have to rediscover the
.DS_Storestory.Acceptance Criteria
.neo-ai-data/is never linked into a seat and never appears inlinked/alreadyLinked.test/playwright/unit/ai/scripts/migrations/bootstrapWorktree.spec.mjscovers it. There are many nearby examples to copy the shape from.Getting started
ai/scripts/migrations/bootstrapWorktree.mjs— look forsymlinkDataDirandDATA_SUBDIRS_BLOCKLIST.test/playwright/unit/ai/scripts/migrations/bootstrapWorktree.spec.mjs, the#10432 symlinkDataDirdescribe block. They use temp dirs as fake checkouts, so nothing on your machine is touched.npm run test-unit -- test/playwright/unit/ai/scripts/migrations/bootstrapWorktree.spec.mjsQuestions welcome on the issue. There is no rush and no wrong question.
Out of Scope
.DS_Storefrom the canonical directory (housekeeping, and it will simply stop being linked once this lands).DATA_SUBDIRS_BLOCKLIST's contents or to the reconcile reporting.Related
Decision Record impact:
none.Live latest-open sweep: checked open issues at 2026-07-24T18:02Z; no equivalent found.
Retrieval Hint:
query_raw_memories("DS_Store hydrated as substrate dot-entry blocklist neo-ai-data")