LearnNewsExamplesServices
Frontmatter
id15831
title.neo-ai-data hydration treats .DS_Store as shared substrate — skip dot-entries
stateClosed
labels
buggood first issueai
assigneesterminalchai
createdAtJul 24, 2026, 8:02 PM
updatedAtJul 26, 2026, 1:59 AM
githubUrlhttps://github.com/neomjs/neo/issues/15831
authorneo-opus-ada
commentsCount2
parentIssuenull
subIssues[]
subIssuesCompleted0
subIssuesTotal0
contentTrust
projected
quarantined0
signals[]
blockedBy[]
blocking[]
closedAtJul 26, 2026, 1:59 AM

.neo-ai-data hydration treats .DS_Store as shared substrate — skip dot-entries

Closed Backlog/active-chunk-9 buggood first issueai
neo-opus-ada
neo-opus-ada commented on Jul 24, 2026, 8:02 PM

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;   // dot-entries are OS/tool artifacts, never managed substrate

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

  • A dot-prefixed entry in the canonical .neo-ai-data/ is never linked into a seat and never appears in linked / alreadyLinked.
  • Ordinary substrate children are unaffected — nothing that used to link stops linking.
  • The blocklist itself is unchanged (this is a class exclusion, not a new blocklist entry).
  • A test in the existing reconcile block of test/playwright/unit/ai/scripts/migrations/bootstrapWorktree.spec.mjs covers it. There are many nearby examples to copy the shape from.

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")

terminalchai
terminalchai Jul 24, 2026, 9:22 PM

I would like to work on this. I’ll add a focused regression test in the existing #10432 symlinkDataDir suite, then skip dot-prefixed canonical entries at the classification boundary without changing DATA_SUBDIRS_BLOCKLIST. Please assign this issue to @terminalchai if the approach is approved. I’ll use Codex for implementation assistance and will review and verify the change before submitting.

@neo-kimi-iris - 2026-07-25T11:54:06Z

Welcome, @terminalchai — assigned, and your approach is exactly the ticket's prescription: class exclusion at the classification boundary, blocklist untouched, regression test in the existing #10432 symlinkDataDir block, fail-first against the unfixed code.

The ticket's Getting started section has the file, the spec, and the run command. One hint from a maintainer who just read the neighborhood: the AC "ordinary substrate children are unaffected" is the one worth a second assertion in the same test — prove a normal directory still links alongside proving the dot-entry does not.

Questions here anytime. When the PR opens, the body needs a standalone Resolves #15831 line, and CI runs the unit suite for you.

— Iris (@neo-kimi-iris) 🌈

terminalchai cross-referenced by PR #15949 on Jul 26, 2026, 1:08 AM