Modules/businessdev.ALbuild.Apps/Public/Set-BcCallGraphAgentHint.ps1

function Set-BcCallGraphAgentHint {
    <#
    .SYNOPSIS
        Tells AI agents in this repository to ask the call graph before searching the code.
 
    .DESCRIPTION
        Writes (or updates) a marked section in CLAUDE.md - or another instructions file such as AGENTS.md -
        that lists the call graph lookups (albuild graph overview / find / show / path) and when to use them.
        Everything outside the markers is left alone; running it again replaces only the section.
 
    .PARAMETER WorkspaceRoot
        Repository root. Default: the current directory.
 
    .PARAMETER File
        The instructions file, relative to the workspace root. Default 'CLAUDE.md'.
 
    .PARAMETER Remove
        Remove the section instead.
 
    .EXAMPLE
        Set-BcCallGraphAgentHint -WorkspaceRoot .
 
    .OUTPUTS
        PSCustomObject: Path, Action (Added, Updated, Unchanged, Removed).
    #>

    [CmdletBinding(SupportsShouldProcess)]
    [OutputType([PSCustomObject])]
    param(
        [string] $WorkspaceRoot,
        [string] $File = 'CLAUDE.md',
        [switch] $Remove
    )

    if (-not $WorkspaceRoot) { $WorkspaceRoot = (Get-Location).ProviderPath }
    $path = Join-Path -Path $WorkspaceRoot -ChildPath $File
    $begin = '<!-- albuild:callgraph -->'
    $end = '<!-- /albuild:callgraph -->'
    $section = @"
$begin
## Call graph
 
This repository has an ALbuild call graph. Before searching the code for where something lives or what a change
touches, ask the graph - it answers from the compiled call graph, across all projects and into Microsoft's apps:
 
- ``albuild graph overview --json``: the parts of the app and how they connect
- ``albuild graph find "<words>" --json``: parts, objects and methods by name or description
- ``albuild graph show "<Codeunit Name>" --json``: an object's part, description, members, callers and callees
- ``albuild graph path --from "<object or part>" --to "<object or part>" --json``: how one reaches the other
- ``albuild graph impact --baseline <graph folder> --json``: what a change affects and which tests reach it
 
Rebuild it with ``albuild graph build`` after larger changes. The parts and descriptions live in
``callgraph.architecture.json``; keep them current when you add or move objects (``albuild graph describe``).
$end
"@

    $content = if (Test-Path -LiteralPath $path) { [System.IO.File]::ReadAllText($path) } else { '' }
    $pattern = '(?s)' + [regex]::Escape($begin) + '.*?' + [regex]::Escape($end) + '\r?\n?'
    $has = [regex]::IsMatch($content, $pattern)
    if ($Remove) {
        $new = [regex]::Replace($content, $pattern, '')
        $action = if ($has) { 'Removed' } else { 'Unchanged' }
    }
    elseif ($has) {
        # A literal replacement: '$' in the section must not be read as a group reference.
        $new = [regex]::Replace($content, $pattern, ($section.Replace("`r`n", "`n") + "`n").Replace('$', '$$'))
        $action = 'Updated'
    }
    else {
        $new = $content.TrimEnd() + $(if ($content.Trim()) { "`n`n" } else { '' }) + $section.Replace("`r`n", "`n") + "`n"
        $action = 'Added'
    }
    if ($new -eq $content) { $action = 'Unchanged' }
    elseif ($PSCmdlet.ShouldProcess($path, "$action the call graph section")) {
        [System.IO.File]::WriteAllText($path, $new, (New-Object System.Text.UTF8Encoding($false)))
        Write-ALbuildLog -Level Success "$action the call graph section in '$path'."
    }
    [PSCustomObject]@{ Path = $path; Action = $action }
}