Payload/scripts/harness/pull-ai-base.ps1
|
#Requires -Version 5.1 <# .SYNOPSIS Pull synced AI base from the Kaden template into this repository. .EXAMPLE .\scripts\harness\pull-ai-base.ps1 -TemplateRoot %USERPROFILE%\Repos_local\kaden .\scripts\harness\setup-kaden-ai-overlays.ps1 -TemplateRoot %USERPROFILE%\Repos_local\kaden .\scripts\harness\setup-harness-hooks.ps1 #> [CmdletBinding(SupportsShouldProcess = $true)] param( [Parameter(Mandatory = $true)] [string]$TemplateRoot, [string]$TargetRoot = '' ) $ErrorActionPreference = 'Stop' # Resolve the destination repo root. This script is the bootstrap entry, so the # target may not have .git, package.json, or scripts/harness yet. if ([string]::IsNullOrWhiteSpace($TargetRoot)) { $scriptDir = if ($PSScriptRoot) { $PSScriptRoot } else { Split-Path -Parent $MyInvocation.MyCommand.Path } $current = (Resolve-Path $scriptDir).Path $resolved = $null # Prefer on-disk markers, walking up from the script. A first-time child # often has only scripts\ + .github\ (or just scripts\), so .git is optional. while ($true) { $hasGit = Test-Path -LiteralPath (Join-Path $current '.git') $hasNodeMarker = Test-Path -LiteralPath (Join-Path $current 'package.json') $hasHarnessInvoke = Test-Path -LiteralPath (Join-Path $current 'scripts\harness-invoke.ps1') $hasHarnessScripts = Test-Path -LiteralPath (Join-Path $current 'scripts\harness') $hasScriptsDir = Test-Path -LiteralPath (Join-Path $current 'scripts') $hasGithubDir = Test-Path -LiteralPath (Join-Path $current '.github') $isEstablishedRepo = $hasGit -or ($hasNodeMarker -and $hasHarnessInvoke) -or ($hasHarnessInvoke -and $hasHarnessScripts) $isBootstrapRepo = $hasScriptsDir -and $hasGithubDir if ($isEstablishedRepo -or $isBootstrapRepo) { $resolved = $current break } $parent = Split-Path $current -Parent if ([string]::IsNullOrWhiteSpace($parent) -or $parent -eq $current) { break } $current = $parent } # No markers (empty folder with only this script). Infer root from where # the script itself lives: # <repo>\scripts\pull-ai-base.ps1 # <repo>\scripts\harness\pull-ai-base.ps1 # <repo>\templates\scripts\harness\pull-ai-base.ps1 if (-not $resolved) { $normalized = $scriptDir.TrimEnd('\', '/') if ($normalized -match '[\\/]templates[\\/]scripts[\\/]harness$') { $resolved = (Resolve-Path (Join-Path $scriptDir '..\..\..')).Path } elseif ($normalized -match '[\\/]scripts[\\/]harness$') { $resolved = (Resolve-Path (Join-Path $scriptDir '..\..')).Path } elseif ($normalized -match '[\\/]scripts$') { $resolved = (Resolve-Path (Join-Path $scriptDir '..')).Path } } if (-not $resolved) { throw "Could not locate repository root from $scriptDir. Pass -TargetRoot <repo-root>." } $TargetRoot = $resolved } # Source paths are relative to -TemplateRoot (the Kaden clone). # Dest paths are relative to the target repo root. # Exclude skips files that must stay in place while this script is running. $pathsToCopy = @( @{ Source = '.github\agents'; Dest = '.github\agents' }, @{ Source = '.github\skills'; Dest = '.github\skills' }, @{ Source = '.github\agents\knowledge'; Dest = '.github\agents\knowledge' }, @{ Source = '.github\prompts'; Dest = '.github\prompts' }, @{ Source = '.github\evals'; Dest = '.github\evals' }, @{ Source = '.github\copilot-instructions.md'; Dest = '.github\copilot-instructions.md' }, @{ Source = '.github\instructions'; Dest = '.github\instructions' }, @{ Source = '.github\templates'; Dest = '.github\templates' }, @{ Source = '.cursor\rules'; Dest = '.cursor\rules\00-from-template' }, @{ Source = '.cursor\hooks'; Dest = '.cursor\hooks' }, @{ Source = 'docs\kaden'; Dest = 'docs' }, @{ Source = 'templates\scripts\harness-invoke.ps1'; Dest = 'scripts\harness-invoke.ps1' }, @{ Source = 'templates\scripts\verify-local.ps1'; Dest = 'scripts\verify-local.ps1' }, # Temporary dest: flatten harness package into templates\scripts, not scripts\harness. # Do not overwrite the running pull-ai-base.ps1 (Copy-Item -Exclude only applies to src\*). @{ Source = 'templates\scripts\harness'; Dest = 'scripts'; Exclude = @('pull-ai-base.ps1') } ) foreach ($item in $pathsToCopy) { $src = Join-Path $TemplateRoot $item.Source $dst = Join-Path $TargetRoot $item.Dest if (-not (Test-Path $src)) { Write-Warning "Skip missing template path: $src" continue } if ($PSCmdlet.ShouldProcess($dst, "Copy from $src")) { if (Test-Path $src -PathType Container) { # Merge into dest. Do not Remove-Item the dest folder - that deletes # the running script and any already-copied siblings. if (-not (Test-Path -LiteralPath $dst)) { New-Item -ItemType Directory -Path $dst -Force | Out-Null } $copyParams = @{ Path = (Join-Path $src '*') Destination = $dst Recurse = $true Force = $true } if ($item.ContainsKey('Exclude') -and $item.Exclude) { $copyParams.Exclude = $item.Exclude } Copy-Item @copyParams } else { $parent = Split-Path $dst -Parent if ($parent -and -not (Test-Path -LiteralPath $parent)) { New-Item -ItemType Directory -Path $parent -Force | Out-Null } Copy-Item -Path $src -Destination $dst -Force } } } # sync-cursor-ai.ps1 currently lands under the temporary templates\scripts dest. # The historical path is scripts\sync-cursor-ai.ps1 - try both. $syncCandidates = @( (Join-Path $TargetRoot 'scripts\sync-cursor-ai.ps1') #(Join-Path $TargetRoot 'templates\scripts\sync-cursor-ai.ps1') ) $syncScript = $syncCandidates | Where-Object { Test-Path -LiteralPath $_ } | Select-Object -First 1 if ($syncScript) { & $syncScript -RepoRoot $TargetRoot } else { Write-Warning "sync-cursor-ai.ps1 not found under scripts\ or templates\scripts\ - run sync manually." } Write-Output "AI base pull complete. Next: .\scripts\harness\setup-kaden-ai-overlays.ps1 -TemplateRoot <path-to-kaden>; then .\scripts\harness\setup-harness-hooks.ps1" |