@zgeoff/atc 2.4.0 → 2.4.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@zgeoff/atc",
3
- "version": "2.4.0",
3
+ "version": "2.4.1",
4
4
  "description": "Terminal control tower for coding-agent sessions",
5
5
  "homepage": "https://github.com/zgeoff/atc#readme",
6
6
  "bugs": "https://github.com/zgeoff/atc/issues",
@@ -4,9 +4,9 @@ import { dirname, join } from 'node:path';
4
4
  /**
5
5
  * The repository a directory belongs to, for clustering sessions in the
6
6
  * overlay. Walks toward the filesystem root looking for a `.git` entry: a
7
- * directory marks the repository root itself, and a linked worktree's `.git`
8
- * file points back at the main repository, so worktrees cluster with it. A
9
- * directory outside any repository resolves to itself.
7
+ * directory holding HEAD marks the repository root itself, and a linked
8
+ * worktree's `.git` file points back at the main repository, so worktrees
9
+ * cluster with it. A directory outside any repository resolves to itself.
10
10
  */
11
11
  export function resolveRepoRoot(cwd: string): string {
12
12
  let dir = cwd;
@@ -15,7 +15,7 @@ export function resolveRepoRoot(cwd: string): string {
15
15
  const marker = join(dir, '.git');
16
16
  const stat = statSync(marker, { throwIfNoEntry: false });
17
17
 
18
- if (stat !== undefined && stat.isDirectory()) {
18
+ if (stat !== undefined && stat.isDirectory() && hasGitHead(marker)) {
19
19
  return dir;
20
20
  }
21
21
 
@@ -33,6 +33,15 @@ export function resolveRepoRoot(cwd: string): string {
33
33
  }
34
34
  }
35
35
 
36
+ /**
37
+ * Whether a `.git` directory is a repository rather than an empty directory
38
+ * that happens to carry the name. git needs HEAD in one, and a stray `.git` in
39
+ * a shared temporary directory would otherwise cluster every session under it.
40
+ */
41
+ function hasGitHead(marker: string): boolean {
42
+ return statSync(join(marker, 'HEAD'), { throwIfNoEntry: false }) !== undefined;
43
+ }
44
+
36
45
  // A linked worktree's `.git` file reads `gitdir: <main>/.git/worktrees/<name>`.
37
46
  function findMainRoot(gitFile: string): string | null {
38
47
  try {