fix: sync living docs (DECISIONS/REQUIREMENTS/PROJECT/KNOWLEDGE) between worktree and project root (#1173)

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
This commit is contained in:
Tom Boucher 2026-03-18 12:07:06 -04:00 committed by GitHub
parent a1ef04a5f3
commit 8281a2ea75

View file

@ -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 ───────────────────────────────────────────────────