Summary
gbrain's submodule heuristic checks only whether .git is a file vs directory. Git worktrees also have .git as a file (the gitdir pointer is the worktree mechanism), so worktrees are incorrectly treated as submodules. This breaks code-sync silently and produces a misleading warning.
Affects every Conductor user (Anthropic's parallel-agent workspace tool), which builds workspaces as git worktrees of a single canonical repo.
Reproduce
git clone https://github.com/<you>/<some-repo>.git ~/code/myrepo
cd ~/code/myrepo
git worktree add /tmp/wt-feature -b feature/xyz
cd /tmp/wt-feature
gbrain sources add gstack-code-wt --path "$(pwd)" --federated
gbrain sync --strategy code --source gstack-code-wt
gbrain sources list | grep gstack-code-wt # page_count=0
Observed (on v0.32.0, also v0.27.0)
Already up to date.
Note: skipping .gitignore management — /tmp/wt-feature is a git submodule. Add db_only directories to your parent repo's .gitignore manually.
page_count for the worktree source stays 0.
gbrain code-def / code-refs / code-callers return nothing for the worktree.
- The warning points at the wrong cause (submodule), so users don't know to investigate worktrees.
Expected
Worktrees should be code-indexed like any normal repo. The submodule warning should fire only for actual submodules.
Root cause
src/commands/sync.ts:1149-1164:
const dotGit = join(repoPath, '.git');
if (existsSync(dotGit)) {
try {
if (statSync(dotGit).isFile()) {
console.warn(`Note: skipping .gitignore management — ${repoPath} is a git submodule. ...`);
return;
}
} catch { ... }
}
isFile() is true for both:
- Submodule
.git: gitdir: ../.git/modules/<name> (relative, contains /modules/)
- Worktree
.git: gitdir: /path/to/main/.git/worktrees/<name> (absolute, contains /worktrees/)
Reading the file and inspecting the gitdir path distinguishes them.
Suggested fix shape
if (st.isFile()) {
const contents = readFileSync(dotGit, 'utf8').trim();
const gitdir = contents.match(/^gitdir:\s*(.+)$/m)?.[1] ?? '';
if (/\/modules\//.test(gitdir)) {
console.warn(`Note: skipping .gitignore management — ${repoPath} is a git submodule. ...`);
return;
}
// worktree (/worktrees/) or unknown — fall through, treat as normal repo
}
Secondary observation
After upgrading 0.27.0 → 0.32.0, gbrain sync --full --strategy code --source <id> against a worktree starts walking files (209 found), but every file errors with:
column "source_id" of relation "ingest_log" does not exist
Re-running gbrain apply-migrations --yes leaves migrations v0.28.0 PARTIAL and v0.29.1 in status=failed with getaddrinfo ENOTFOUND (target host unknown — DNS resolves fine for aws-1-us-east-1.pooler.supabase.com and api.openai.com). Doctor reports MINIONS HALF-INSTALLED. May share a root cause with the worktree detection; flagging in case. Happy to file separately if preferred.
Environment
- gbrain v0.27.0 (originally) and v0.32.0 (after upgrade) — both reproduce
- macOS 26.4.1, bash
- Brain engine: postgres (Supabase pooler)
- Worktree pattern: Anthropic Conductor (each workspace =
git worktree add from a canonical clone)
Summary
gbrain's submodule heuristic checks only whether
.gitis a file vs directory. Git worktrees also have.gitas a file (the gitdir pointer is the worktree mechanism), so worktrees are incorrectly treated as submodules. This breaks code-sync silently and produces a misleading warning.Affects every Conductor user (Anthropic's parallel-agent workspace tool), which builds workspaces as git worktrees of a single canonical repo.
Reproduce
Observed (on v0.32.0, also v0.27.0)
page_countfor the worktree source stays0.gbrain code-def/code-refs/code-callersreturn nothing for the worktree.Expected
Worktrees should be code-indexed like any normal repo. The submodule warning should fire only for actual submodules.
Root cause
src/commands/sync.ts:1149-1164:isFile()is true for both:.git:gitdir: ../.git/modules/<name>(relative, contains/modules/).git:gitdir: /path/to/main/.git/worktrees/<name>(absolute, contains/worktrees/)Reading the file and inspecting the gitdir path distinguishes them.
Suggested fix shape
Secondary observation
After upgrading 0.27.0 → 0.32.0,
gbrain sync --full --strategy code --source <id>against a worktree starts walking files (209 found), but every file errors with:Re-running
gbrain apply-migrations --yesleaves migrations v0.28.0 PARTIAL and v0.29.1 instatus=failedwithgetaddrinfo ENOTFOUND(target host unknown — DNS resolves fine foraws-1-us-east-1.pooler.supabase.comandapi.openai.com). Doctor reportsMINIONS HALF-INSTALLED. May share a root cause with the worktree detection; flagging in case. Happy to file separately if preferred.Environment
git worktree addfrom a canonical clone)