# Sync project templates to target project. # - Copies templates/memory-bank/ -> /memory-bank/ # - Copies templates/prompts/ -> /docs/prompts/ # - Copies templates/AGENTS.template.md -> /AGENTS.md # - Copies templates/AGENT_RULES.template.md -> /AGENT_RULES.md # Existing targets are backed up before overwrite. [CmdletBinding()] param( [Parameter(Mandatory = $false)] [Alias('h', '?')] [switch]$Help, [Parameter(Mandatory = $false)] [string]$ProjectRoot, [Parameter(Mandatory = $false)] [string]$ProjectName, [Parameter(Mandatory = $false)] [string]$Date, [Parameter(Mandatory = $false)] [switch]$NoBackup, [Parameter(Mandatory = $false)] [switch]$Force, [Parameter(Mandatory = $false)] [switch]$Full ) $ErrorActionPreference = "Stop" if ($Help) { Write-Host "Usage:" Write-Host " powershell -File scripts/sync_templates.ps1 [options]" Write-Host " powershell -File scripts/sync_templates.ps1 -ProjectRoot C:\\path\\to\\project" Write-Host "" Write-Host "Options:" Write-Host " -ProjectRoot PATH Target project root (default: git root)." Write-Host " -ProjectName NAME Replace {{PROJECT_NAME}} placeholder." Write-Host " -Date DATE Replace {{DATE}} placeholder (default: today)." Write-Host " -NoBackup Skip backup of existing files." Write-Host " -Force Overwrite without prompting." Write-Host " -Full Append full framework section to AGENTS.md." Write-Host " -Help Show this help." exit 0 } $ScriptDir = Split-Path -Parent $MyInvocation.MyCommand.Path $Src = (Resolve-Path (Join-Path $ScriptDir "..")).Path # Defaults if (-not $Date) { $Date = Get-Date -Format "yyyy-MM-dd" } # Determine project root if (-not $ProjectRoot) { $ProjectRoot = (git -C $ScriptDir rev-parse --show-toplevel 2>$null) if (-not $ProjectRoot) { $ProjectRoot = (Get-Location).Path } } $ProjectRoot = (Resolve-Path $ProjectRoot).Path # Source directories $TemplatesDir = Join-Path $Src "templates" $MemoryBankSrc = Join-Path $TemplatesDir "memory-bank" $PromptsSrc = Join-Path $TemplatesDir "prompts" $AgentsSrc = Join-Path $TemplatesDir "AGENTS.template.md" $AgentRulesSrc = Join-Path $TemplatesDir "AGENT_RULES.template.md" # Check source exists if (-not (Test-Path $TemplatesDir)) { throw "Templates directory not found: $TemplatesDir" } # Skip if source equals destination if ($Src -ieq $ProjectRoot) { Write-Host "Skip: playbook root equals project root." Write-Host "Done." exit 0 } $timestamp = Get-Date -Format "yyyyMMddHHmmss" # Function: backup file/directory function Backup-IfExists { param([string]$Target) if ((Test-Path $Target) -and -not $NoBackup) { $backup = "$Target.bak.$timestamp" Move-Item $Target $backup Write-Host "Backed up: $(Split-Path -Leaf $Target) -> $(Split-Path -Leaf $backup)" } } # Function: replace placeholders in file function Replace-Placeholders { param([string]$File) if (-not (Test-Path $File)) { return } $content = Get-Content -Raw -Path $File if ($ProjectName) { $content = $content.Replace("{{PROJECT_NAME}}", $ProjectName) } $content = $content.Replace("{{DATE}}", $Date) Set-Content -Path $File -Value $content -Encoding UTF8 -NoNewline } # Function: replace placeholders in directory function Replace-PlaceholdersDir { param([string]$Dir) if (-not (Test-Path $Dir)) { return } Get-ChildItem -Path $Dir -Filter "*.md" -Recurse -File | ForEach-Object { Replace-Placeholders -File $_.FullName } } Write-Host "Syncing templates to: $ProjectRoot" Write-Host "" # 1. Sync memory-bank/ if (Test-Path $MemoryBankSrc) { $MemoryBankDst = Join-Path $ProjectRoot "memory-bank" if ((Test-Path $MemoryBankDst) -and -not $Force) { Write-Host "memory-bank/ already exists. Use -Force to overwrite." } else { Backup-IfExists -Target $MemoryBankDst New-Item -ItemType Directory -Path $MemoryBankDst -Force | Out-Null Copy-Item -Path (Join-Path $MemoryBankSrc "*") -Destination $MemoryBankDst -Recurse -Force # Rename .template.md to .md Get-ChildItem -Path $MemoryBankDst -Filter "*.template.md" -File | ForEach-Object { $newName = $_.Name -replace "\.template\.md$", ".md" Rename-Item -Path $_.FullName -NewName $newName } Replace-PlaceholdersDir -Dir $MemoryBankDst Write-Host "Synced: memory-bank/" } } else { Write-Host "Skip: memory-bank/ templates not found" } # 2. Sync docs/prompts/ if (Test-Path $PromptsSrc) { $PromptsDst = Join-Path $ProjectRoot "docs\prompts" if ((Test-Path $PromptsDst) -and -not $Force) { Write-Host "docs/prompts/ already exists. Use -Force to overwrite." } else { Backup-IfExists -Target $PromptsDst $DocsDir = Join-Path $ProjectRoot "docs" New-Item -ItemType Directory -Path $DocsDir -Force | Out-Null New-Item -ItemType Directory -Path $PromptsDst -Force | Out-Null Copy-Item -Path (Join-Path $PromptsSrc "*") -Destination $PromptsDst -Recurse -Force # Rename .template.md to .md recursively Get-ChildItem -Path $PromptsDst -Filter "*.template.md" -Recurse -File | ForEach-Object { $newName = $_.Name -replace "\.template\.md$", ".md" Rename-Item -Path $_.FullName -NewName $newName } Replace-PlaceholdersDir -Dir $PromptsDst Write-Host "Synced: docs/prompts/" } } else { Write-Host "Skip: prompts/ templates not found" } # 3. Sync AGENTS.md # Choose markers based on -Full flag if ($Full) { $MarkerStart = "" $MarkerEnd = "" $SectionName = "framework" } else { $MarkerStart = "" $MarkerEnd = "" $SectionName = "templates" } if (Test-Path $AgentsSrc) { $AgentsDst = Join-Path $ProjectRoot "AGENTS.md" if (-not (Test-Path $AgentsDst)) { # AGENTS.md doesn't exist: create from full template Copy-Item -Path $AgentsSrc -Destination $AgentsDst -Force Replace-Placeholders -File $AgentsDst Write-Host "Created: AGENTS.md" } else { # AGENTS.md exists: update or append section # Extract snippet from template $templateContent = Get-Content -Raw -Path $AgentsSrc $extractPattern = "(?s)(" + [regex]::Escape($MarkerStart) + ".*?" + [regex]::Escape($MarkerEnd) + ")" if ($templateContent -match $extractPattern) { $snippetContent = $Matches[1] $content = Get-Content -Raw -Path $AgentsDst if ($content -match [regex]::Escape($MarkerStart)) { # Has markers: replace content between markers $replacePattern = "(?s)" + [regex]::Escape($MarkerStart) + ".*?" + [regex]::Escape($MarkerEnd) $newContent = $content -replace $replacePattern, $snippetContent Set-Content -Path $AgentsDst -Value $newContent -Encoding UTF8 -NoNewline Replace-Placeholders -File $AgentsDst Write-Host "Updated: AGENTS.md ($SectionName section)" } else { # No markers: append snippet at the end $newContent = $content.TrimEnd() + "`n`n" + $snippetContent Set-Content -Path $AgentsDst -Value $newContent -Encoding UTF8 -NoNewline Replace-Placeholders -File $AgentsDst Write-Host "Appended: AGENTS.md ($SectionName section)" } } else { Write-Host "Skip: markers not found in template" } } } else { Write-Host "Skip: AGENTS.template.md not found" } # 4. Sync AGENT_RULES.md if (Test-Path $AgentRulesSrc) { $AgentRulesDst = Join-Path $ProjectRoot "AGENT_RULES.md" if ((Test-Path $AgentRulesDst) -and -not $Force) { Write-Host "AGENT_RULES.md already exists. Use -Force to overwrite." } else { Backup-IfExists -Target $AgentRulesDst Copy-Item -Path $AgentRulesSrc -Destination $AgentRulesDst -Force Replace-Placeholders -File $AgentRulesDst Write-Host "Synced: AGENT_RULES.md" } } else { Write-Host "Skip: AGENT_RULES.template.md not found" } Write-Host "" Write-Host "Done." Write-Host "" Write-Host "Next steps:" Write-Host " 1. Edit memory-bank/*.md to fill in project-specific content" Write-Host " 2. Replace remaining {{PLACEHOLDER}} values" Write-Host " 3. Run sync_standards.ps1 to sync .agents/ rules"