249 lines
8.1 KiB
PowerShell
249 lines
8.1 KiB
PowerShell
# 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', '?')]
|
|
[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 = "<!-- 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"
|
|
}
|
|
|
|
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"
|