fix(git-sync): self-heal a missing 'main' branch that wedged a space (D3-N1)

Ref-store damage (a deleted refs/heads/main, an interrupted ref update) can leave an
existing vault repo without a 'main' branch. The cycle's ensureBranch('docmost','main')
+ checkout then throw every poll ("pathspec 'main' did not match"), wedging the space
forever with no self-heal — ensureRepo only creates branches on a FRESH git init
(found via web-test corruption charter, reproduced deterministically).

Add VaultGit.ensureMainBranch() and call it in the cycle preflight (after
clearStaleGitLocks, before the branch setup): if 'main' is missing, re-create it from
the 'docmost' mirror branch (they track each other) else from HEAD. Same
wedge-forever family as D3-N3.

Verified on the stand: deleting refs/heads/main now self-heals (main restored, the
edit reaches the vault, 0 pathspec errors) — was wedged forever. Unit test (real temp
repo: delete main -> ensureMainBranch restores it from docmost). git-sync suite green (708).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-07-03 07:34:17 +03:00
parent f0778cb85a
commit d218b3a39e
5 changed files with 58 additions and 0 deletions
+26
View File
@@ -166,6 +166,32 @@ describe('VaultGit (integration; temp repo)', () => {
await expect(git.clearStaleGitLocks()).resolves.toBeUndefined();
});
it('ensureMainBranch restores a deleted main from the docmost mirror (bug D3-N1)', async () => {
if (!available) return;
const vault = await freshDir();
const git = new VaultGit(vault);
await git.ensureRepo();
await git.ensureBranch('docmost', 'main');
// Ref damage: delete refs/heads/main (git refuses to delete the current
// branch, so move HEAD to docmost first — simulating a lost main ref).
await execFileAsync('git', ['symbolic-ref', 'HEAD', 'refs/heads/docmost'], {
cwd: vault,
});
await execFileAsync('git', ['branch', '-D', 'main'], { cwd: vault });
await expect(
execFileAsync('git', ['rev-parse', '--verify', 'main'], { cwd: vault }),
).rejects.toThrow();
// The preflight re-creates main (from docmost).
await git.ensureMainBranch();
await expect(
execFileAsync('git', ['rev-parse', '--verify', 'main'], { cwd: vault }),
).resolves.toBeDefined();
// Idempotent when main already exists.
await expect(git.ensureMainBranch()).resolves.toBeUndefined();
});
it('ensureRepo neutralizes correctness-affecting LOCAL config', async () => {
if (!available) return;
const vault = await freshDir();