Private/Update-KadenInstructionBlock.ps1

function Update-KadenInstructionBlock {
    <#
    .SYNOPSIS
        Create or refresh delimited Kaden blocks without wiping project text.
    .DESCRIPTION
        AGENTS.md receives a project header only when it is missing and -CreateMissingAgents
        is set. Update leaves a missing AGENTS.md alone. A missing .github/copilot-instructions.md
        is created with a short project header and the delimited block. A file that already
        exists changes only between <!-- KADEN:START --> and <!-- KADEN:END -->.
        A broken marker pair is left untouched and reported.
    #>

    [Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSUseShouldProcessForStateChangingFunctions', '', Justification = 'Initialize-KadenRepo and Update-KadenRepo already confirm ShouldProcess before this private write.')]
    [CmdletBinding()]
    param(
        [Parameter(Mandatory = $true)]
        [string]$ChildRoot,

        [Parameter(Mandatory = $true)]
        [string]$ProjectId,

        [Parameter(Mandatory = $false)]
        [switch]$CreateMissingAgents,

        [Parameter(Mandatory = $false)]
        [switch]$AssumeLock
    )

    if ($CreateMissingAgents -and -not (Test-KadenProjectId -ProjectId $ProjectId)) {
        throw 'KDN-PROJECT-ID-INVALID: ProjectId must be at most 64 characters of lowercase letters, digits, and single hyphens.'
    }

    $contract = @{
        StartToken = '<!-- KADEN:START -->'
        EndToken   = '<!-- KADEN:END -->'
        Notice     = '<!-- Managed by Kaden. Do not edit content within this block. -->'
    }
    $agentsBody = Get-KadenInstructionBodyText -LiteralPath (Join-Path $script:KadenModuleRoot (Join-Path 'InstructionBlocks' 'agents-block.md'))
    $copilotSource = Join-Path (Get-KadenPayloadRoot) (Join-Path 'github' 'copilot-instructions.md')
    $copilotBody = Get-KadenInstructionBodyText -LiteralPath $copilotSource
    $findings = New-Object System.Collections.Generic.List[string]
    $delimitedDestinations = @(Get-KadenDelimitedInstructionDestination)
    $copilotRelative = $null
    foreach ($destination in $delimitedDestinations) {
        if ($destination -eq '.github/copilot-instructions.md') {
            $copilotRelative = $destination
            break
        }
    }
    if (-not $copilotRelative) {
        throw 'KDN-INSTRUCTION-DESTINATION-MISSING: managed manifest has no delimited instruction destination.'
    }

    $agentsHeader = @(
        "# AGENTS.md - $ProjectId"
        ''
        'Project commands and notes stay outside the Kaden markers.'
        ''
        '## Commands'
        ''
        '| Action | Command |'
        '|--------|---------|'
        '| Harness entry | `pwsh -File scripts/kaden/harness-invoke.ps1 <harness-script> [args...]` |'
        ''
    ) -join "`n"
    $copilotHeader = @(
        '# Project Copilot instructions'
        ''
        'Project policy stays outside the Kaden markers.'
        ''
    ) -join "`n"

    $transactionId = [guid]::NewGuid().ToString('N')
    $lockPath = Join-Path $ChildRoot (Join-Path '.kaden' (Join-Path 'transactions' 'update.lock'))
    if (-not $AssumeLock) {
        Lock-KadenUpdate -LockPath $lockPath -TransactionId $transactionId
    }
    try {
        $agentsContent = @{
            Header            = $agentsHeader
            Body              = $agentsBody
            CreateWhenMissing = [bool]$CreateMissingAgents
            StartToken        = $contract.StartToken
            EndToken          = $contract.EndToken
            Notice            = $contract.Notice
        }
        $copilotContent = @{
            Header            = $copilotHeader
            Body              = $copilotBody
            CreateWhenMissing = $true
            StartToken        = $contract.StartToken
            EndToken          = $contract.EndToken
            Notice            = $contract.Notice
        }
        Update-KadenDelimitedInstructionFile -ChildRoot $ChildRoot -RelativePath 'AGENTS.md' -Content $agentsContent -Findings $findings
        Update-KadenDelimitedInstructionFile -ChildRoot $ChildRoot -RelativePath $copilotRelative -Content $copilotContent -Findings $findings
    }
    finally {
        if (-not $AssumeLock) {
            Remove-Item -LiteralPath $lockPath -Force -ErrorAction SilentlyContinue
        }
    }

    foreach ($finding in @($findings)) {
        Write-Warning $finding
    }
    return @($findings)
}