fix: remove preferences.md from ROOT_STATE_FILES to prevent back-sync overwrite

preferences.md was in ROOT_STATE_FILES which caused syncWorktreeStateBack()
to overwrite the project root's authoritative copy with the worktree's
stale copy. The forward-sync (main → worktree) is already handled
separately in syncGsdStateToWorktree() as additive-only.

Fixes the failing CI test:
  worktree-preferences-sync.test.ts:107
  '#2684: syncWorktreeStateBack does NOT overwrite project root preferences.md'

Also updates preferences-worktree-sync.test.ts to assert preferences.md
is NOT in ROOT_STATE_FILES (it must be handled separately).
This commit is contained in:
mastertyko 2026-03-26 23:57:17 +01:00
parent cceee1d196
commit 523e910f21
2 changed files with 16 additions and 6 deletions

View file

@ -82,8 +82,10 @@ const ROOT_STATE_FILES = [
"QUEUE.md",
"completed-units.json",
"metrics.json",
"preferences.md", // #2684: without this, post_unit_hooks and all preference-driven
// config silently stop working inside worktrees.
// NOTE: preferences.md is intentionally NOT in ROOT_STATE_FILES.
// Forward-sync (main → worktree) is handled explicitly in syncGsdStateToWorktree().
// Back-sync (worktree → main) must NEVER overwrite the project root's copy
// because the project root is authoritative for preferences (#2684).
] as const;
/**

View file

@ -11,7 +11,7 @@ import { readFileSync, mkdtempSync, mkdirSync, writeFileSync, existsSync, rmSync
import { join } from "node:path";
import { tmpdir } from "node:os";
test("#2684: ROOT_STATE_FILES includes preferences.md", () => {
test("#2684: preferences.md is NOT in ROOT_STATE_FILES (forward-only sync)", () => {
const srcPath = join(import.meta.dirname, "..", "auto-worktree.ts");
const src = readFileSync(srcPath, "utf-8");
@ -19,12 +19,20 @@ test("#2684: ROOT_STATE_FILES includes preferences.md", () => {
assert.ok(constIdx !== -1, "ROOT_STATE_FILES constant exists");
const arrayStart = src.indexOf("[", constIdx);
const arrayEnd = src.indexOf("]", arrayStart);
const arrayEnd = src.indexOf("] as const", arrayStart);
const block = src.slice(arrayStart, arrayEnd);
// preferences.md must NOT be in ROOT_STATE_FILES — it is handled separately
// in syncGsdStateToWorktree() (forward-only, additive). Including it in
// ROOT_STATE_FILES would cause syncWorktreeStateBack() to overwrite the
// authoritative project root copy (#2684).
const entries = block.split("\n")
.map(l => l.trim())
.filter(l => l.startsWith('"') && l.includes(".md"));
const hasPrefs = entries.some(l => l.includes("preferences.md"));
assert.ok(
block.includes("preferences.md"),
"preferences.md should be in ROOT_STATE_FILES list",
!hasPrefs,
"preferences.md must NOT be in ROOT_STATE_FILES (back-sync would overwrite root)",
);
});