From 8281a2ea755c309e34d569104897cc81867c7037 Mon Sep 17 00:00:00 2001 From: Tom Boucher Date: Wed, 18 Mar 2026 12:07:06 -0400 Subject: [PATCH] fix: sync living docs (DECISIONS/REQUIREMENTS/PROJECT/KNOWLEDGE) between worktree and project root (#1173) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit syncStateToProjectRoot() copied STATE.md, milestone directories, completed-units.json, and runtime records — but not the four root-level living documents. When agents updated these during slice execution in a worktree, a new session would read stale copies from the project root, losing decisions, requirement status changes, project descriptions, and accumulated knowledge. Added bidirectional sync for DECISIONS.md, REQUIREMENTS.md, PROJECT.md, and KNOWLEDGE.md: - Worktree → project root: in syncStateToProjectRoot() after runtime records - Project root → worktree: in syncProjectRootToWorktree() before milestone sync Fixes #1168 --- src/resources/extensions/gsd/auto-worktree-sync.ts | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/src/resources/extensions/gsd/auto-worktree-sync.ts b/src/resources/extensions/gsd/auto-worktree-sync.ts index f13b7631d..5231917c7 100644 --- a/src/resources/extensions/gsd/auto-worktree-sync.ts +++ b/src/resources/extensions/gsd/auto-worktree-sync.ts @@ -36,6 +36,12 @@ export function syncProjectRootToWorktree(projectRoot: string, worktreePath: str // has newer artifacts (e.g. slices that don't exist in the worktree yet) safeCopyRecursive(join(prGsd, "milestones", milestoneId), join(wtGsd, "milestones", milestoneId)) + // Copy living documents from project root to worktree so agents have the + // latest decisions, requirements, project state, and knowledge. + for (const doc of ["DECISIONS.md", "REQUIREMENTS.md", "PROJECT.md", "KNOWLEDGE.md"]) { + safeCopy(join(prGsd, doc), join(wtGsd, doc), { force: true }); + } + // Delete worktree gsd.db so it rebuilds from the freshly synced files. // Stale DB rows are the root cause of the infinite skip loop (#853). try { @@ -89,6 +95,14 @@ export function syncStateToProjectRoot(worktreePath: string, projectRoot: string // worktree. If the next session resolves basePath before worktree re-entry, // selfHeal can't find or clear the stale record (#769). safeCopyRecursive(join(wtGsd, "runtime", "units"), join(prGsd, "runtime", "units"), { force: true }) + + // 5. Living documents — decisions, requirements, project description, knowledge. + // Agents update these during slice execution. Without syncing, a new session + // reads stale copies from the project root, losing architectural decisions, + // requirement status updates, and accumulated knowledge (#1168). + for (const doc of ["DECISIONS.md", "REQUIREMENTS.md", "PROJECT.md", "KNOWLEDGE.md"]) { + safeCopy(join(wtGsd, doc), join(prGsd, doc), { force: true }); + } } // ─── Resource Staleness ───────────────────────────────────────────────────