playbook/scripts/sync_templates.ps1

285 lines
8.6 KiB
PowerShell
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# Sync project templates to target project.
# - Copies templates/memory-bank/ -> <project-root>/memory-bank/
# - Copies templates/prompts/ -> <project-root>/docs/prompts/
# - Copies templates/AGENTS.template.md -> <project-root>/AGENTS.md
# - Copies templates/AGENT_RULES.template.md -> <project-root>/AGENT_RULES.md
# Existing targets are backed up before overwrite.
[CmdletBinding()]
param(
[Parameter(Mandatory = $false)]
[Alias('h', 'help', '?')]
[switch]$Help,
[Parameter(Mandatory = $false, Position = 0)]
[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] [project-root]"
Write-Host ""
Write-Host "Options:"
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 = "<!-- playbook:framework:start -->"
$MarkerEnd = "<!-- playbook:framework:end -->"
$SectionName = "framework"
} else {
$MarkerStart = "<!-- playbook:templates:start -->"
$MarkerEnd = "<!-- playbook:templates:end -->"
$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"
}
# 5. Create TODO.md and CONFIRM.md if not exist
$TodoPath = Join-Path $ProjectRoot "TODO.md"
if (-not (Test-Path $TodoPath)) {
@"
# TODO
## Plan 1: []
- [ ] 1
- [ ] 2
---
****$Date
"@ | Set-Content -Path $TodoPath -Encoding UTF8
Write-Host "Created: TODO.md"
}
$ConfirmPath = Join-Path $ProjectRoot "CONFIRM.md"
if (-not (Test-Path $ConfirmPath)) {
@"
#
##
<!-- -->
##
<!-- -->
---
****$Date
"@ | Set-Content -Path $ConfirmPath -Encoding UTF8
Write-Host "Created: CONFIRM.md"
}
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"