Modules/businessdev.ALbuild.Apps/Public/New-BcCallGraphArchitecture.ps1

function New-BcCallGraphArchitecture {
    <#
    .SYNOPSIS
        Writes a starting callgraph.architecture.json without AI, and worksheets for whoever refines it.
 
    .DESCRIPTION
        The architecture file names the parts of the app, assigns objects to them, describes objects and
        lists flows and a start tour. The call graph report and the build tab read it from the workspace root;
        without it they derive the parts from the folders.
 
        This command needs no AI. It writes:
          - callgraph.architecture.json: the folder-based parts (one per source folder, large folders split
            further). Part summaries, flows and the tour are left empty. Object descriptions are not copied:
            the /// summary in an object's source describes it anyway, so "objects" is only for objects without
            one, or to override it. An existing file is kept unless -Force.
          - with -WorksheetFolder: one Markdown worksheet per part listing its objects, their members, what
            they use and what uses them, and the current descriptions. An agent (or a person) reads them to
            choose better parts and write the descriptions, flows and tour; Test-BcCallGraphArchitecture checks
            the result.
 
    .PARAMETER GraphPath
        The call graph folder written by New-BcCallGraph.
 
    .PARAMETER WorkspaceRoot
        Repository root. Default: recorded by New-BcCallGraph.
 
    .PARAMETER Path
        The architecture file. Default '<WorkspaceRoot>\callgraph.architecture.json'.
 
    .PARAMETER WorksheetFolder
        Write one worksheet per part into this folder.
 
    .PARAMETER Force
        Replace an existing architecture file with the scaffold.
 
    .EXAMPLE
        New-BcCallGraphArchitecture -GraphPath .albuild/callgraph -WorksheetFolder .albuild/callgraph/worksheets
 
    .OUTPUTS
        PSCustomObject: Path, Written, Parts, Objects, DescribedObjects, Worksheets.
    #>

    [CmdletBinding(SupportsShouldProcess)]
    [OutputType([PSCustomObject])]
    param(
        [Parameter(Mandatory)] [string] $GraphPath,
        [string] $WorkspaceRoot,
        [string] $Path,
        [string] $WorksheetFolder,
        [switch] $Force
    )

    $context = Get-BcCallGraphContext -GraphPath $GraphPath -WorkspaceRoot $WorkspaceRoot
    if (-not $context.WorkspaceRoot) { throw 'The workspace root is unknown; pass -WorkspaceRoot.' }
    if (-not $Path) { $Path = Join-Path -Path $context.WorkspaceRoot -ChildPath 'callgraph.architecture.json' }
    $exists = Test-Path -LiteralPath $Path

    $written = $false
    # The scaffold is always derived from the folders, whatever an existing file says.
    $fallback = [ALbuild.CallGraph.Analyzer]::Open($context.Graph.GraphPath, $context.Apps, $context.WorkspaceRoot, $null)
    if (-not $exists -or $Force) {
        if ($PSCmdlet.ShouldProcess($Path, 'Write the callgraph.architecture.json scaffold')) {
            $doc = [ALbuild.CallGraph.Architecture]::Scaffold($fallback.Architecture, $context.WorkspaceRoot)
            New-Item -ItemType Directory -Force -Path (Split-Path -Parent $Path) | Out-Null
            [System.IO.File]::WriteAllText($Path, [ALbuild.CallGraph.Json]::Pretty($doc) + "`n", (New-Object System.Text.UTF8Encoding($false)))
            $written = $true
            Write-ALbuildLog -Level Success "Wrote '$Path': $($fallback.Architecture.Parts.Count) parts from the folders; the /// summaries of $($fallback.Architecture.Descriptions.Count) objects apply without being copied."
        }
    }
    else {
        Write-ALbuildLog "Kept the existing '$Path' (use -Force to replace it with the scaffold)."
    }

    # Worksheets describe the architecture as it now is (the file when there is one).
    $current = [ALbuild.CallGraph.Analyzer]::Open($context.Graph.GraphPath, $context.Apps, $context.WorkspaceRoot, $(if (Test-Path -LiteralPath $Path) { $Path } else { $null }))
    $sheets = @()
    if ($WorksheetFolder -and $PSCmdlet.ShouldProcess($WorksheetFolder, 'Write the call graph worksheets')) {
        New-Item -ItemType Directory -Force -Path $WorksheetFolder | Out-Null
        foreach ($part in $current.Architecture.Parts) {
            $file = Join-Path -Path $WorksheetFolder -ChildPath ("$($part.Id).md" -replace '[^\w\.\-]', '_')
            [System.IO.File]::WriteAllText($file, $current.Explorer.Worksheet($part), (New-Object System.Text.UTF8Encoding($false)))
            $sheets += $file
        }
        Write-ALbuildLog "Wrote $($sheets.Count) worksheet(s) to '$WorksheetFolder'."
    }
    foreach ($w in $current.Architecture.Warnings) { Write-ALbuildLog -Level Warning "Architecture: $w" }

    [PSCustomObject]@{
        Path             = $Path
        Written          = $written
        Parts            = $current.Architecture.Parts.Count
        Objects          = $current.Architecture.Objects.Count
        DescribedObjects = @($current.Architecture.Objects | Where-Object { $current.Architecture.Descriptions.ContainsKey($_.Label) }).Count
        Worksheets       = $sheets
    }
}