Public/Initialize-KadenRepo.ps1
|
function Initialize-KadenRepo { <# .SYNOPSIS Initialize a child repository from the installed Kaden payload. .DESCRIPTION When this installed release channel is beta, validates the PascalCase beta invitation passphrase before any repository change. A missing or incorrectly formed -BetaInvitation fails with KDN-BETA-INVITATION-INVALID and does not change the repository. When the installed release channel is ga, beta acknowledgement is not requested. Then checks the embedded payload, applies allowlisted managed files, and writes `.kaden.json` / `.kaden.local.json`. When shared configuration is absent and `.sync-project-id` holds a valid project identity, that identity is recorded and the legacy file is left unchanged. A later general-availability install does not change an earlier installed copy. Missing starter READMEs are created under docs/adr/, docs/harness/, docs/harness/features/, and docs/wip/. A missing AGENTS.md is created with a project header and command table outside the markers. The markers are <!-- KADEN:START --> and <!-- KADEN:END -->. An existing AGENTS.md or .github/copilot-instructions.md changes only between those markers. A malformed marker pair is left unchanged and listed on InstructionFindings. Project instruction overlays under .github/instructions/ are not modified. The base Copilot instructions file .github/copilot-instructions.md receives the same delimited block. -Stack selects which missing starter configs to seed. Existing matrix files are never overwritten. Recommended doc folders are created with starter READMEs when those READMEs are missing. .PARAMETER Path Child repository root to initialize. .PARAMETER ProjectId Project identity recorded in `.kaden.json` when shared configuration is new. .PARAMETER BetaInvitation PascalCase beta invitation required while the installed channel is beta. Consumers paste the passphrase a maintainer already gave them. New-KadenBetaInvitation is for the maintainer, not for consumers. .PARAMETER Stack Starter stack seeded when the matching files are missing. Valid values are Node, PowerShell, Python, SQL, Polyglot, and None. The default is None. None seeds .editorconfig, .gitattributes, and .vscode/settings.json. Node also seeds eslint.config.mjs, .jsbeautifyrc, stryker.config.mjs, and vitest.config.js. PowerShell also seeds PSScriptAnalyzerSettings.psd1, PowerShellLintPaths.psd1, and powershell-security.semgrep.yml. Python also seeds .pre-commit-config.yaml and requirements.txt. SQL also seeds .sqlfluff and .sqlfluffignore. Polyglot seeds every file named for Node, PowerShell, Python, and SQL. Existing matrix files are left unchanged on initialize and on update. .EXAMPLE # Maintainer dogfood. Consumers paste the passphrase they were given. $invite = New-KadenBetaInvitation Initialize-KadenRepo -Path . -ProjectId 'mac-test-suite' -BetaInvitation $invite .EXAMPLE # Maintainer dogfood with a stack seed. Consumers paste the passphrase they were given. $invite = New-KadenBetaInvitation Initialize-KadenRepo -Path . -ProjectId 'mac-test-suite' -BetaInvitation $invite -Stack Node .EXAMPLE # This installed module is beta. Omitting -BetaInvitation fails with # KDN-BETA-INVITATION-INVALID and does not change the repository. # A later package whose channel is ga accepts initialize without -BetaInvitation. .NOTES On the beta channel the failure code is KDN-BETA-INVITATION-INVALID. #> [CmdletBinding(SupportsShouldProcess = $true)] param( [Parameter(Mandatory = $true)] [string]$Path, [Parameter(Mandatory = $true)] [string]$ProjectId, [Parameter(Mandatory = $false)] [AllowEmptyString()] [string]$BetaInvitation, [Parameter(Mandatory = $false)] [ValidateSet('Node', 'PowerShell', 'Python', 'SQL', 'Polyglot', 'None')] [string]$Stack = 'None' ) $childRoot = Resolve-KadenChildRoot -Path $Path if (-not (Test-Path -LiteralPath $childRoot)) { throw "KDN-TXN-PREFLIGHT-FAILED: Child repository path does not exist: $childRoot" } $channel = Get-KadenReleaseChannel if ($channel -eq 'ga') { $guidance = 'General-availability release: no beta invitation needed. Earlier installed copies stay on the machine unchanged.' } else { $invitation = Test-KadenBetaInvitation -Invitation ([string]$BetaInvitation) if (-not $invitation.Valid) { throw $invitation.Message } $guidance = $invitation.Message } if (-not $PSCmdlet.ShouldProcess($childRoot, 'Initialize-KadenRepo')) { return } $payload = Test-KadenPackagePayload if (-not $payload.Valid) { throw $payload.Message } $moduleVersion = Get-KadenRunningModuleVersion $effectiveProjectId = $ProjectId $sharedPath = Join-Path $childRoot '.kaden.json' if (-not (Test-Path -LiteralPath $sharedPath)) { $legacyProjectId = Get-KadenLegacyProjectId -ChildRoot $childRoot if (-not [string]::IsNullOrWhiteSpace($legacyProjectId)) { $effectiveProjectId = $legacyProjectId } } if (-not (Test-KadenProjectId -ProjectId $effectiveProjectId)) { throw 'KDN-PROJECT-ID-INVALID: ProjectId must be at most 64 characters of lowercase letters, digits, and single hyphens.' } $instructionFindings = @(Invoke-KadenManagedInstructionUpdate -ChildRoot $childRoot -ProjectId $effectiveProjectId ` -Manifest $payload.Manifest -PayloadRoot (Get-KadenPayloadRoot) -ModuleVersion $moduleVersion -CreateMissingAgents) Add-KadenWorkspaceSeed -ChildRoot $childRoot -Stack $Stack return [pscustomobject]@{ Succeeded = $true Path = $childRoot ProjectId = $effectiveProjectId AppliedVersion = $moduleVersion Guidance = $guidance InstructionFindings = $instructionFindings } } |