Public/Get-RaidinessIntake.ps1

function Get-RaidinessIntake {
    <#
    .SYNOPSIS
        The intake questionnaire: the questions, and any answers already given.

    .DESCRIPTION
        Roughly seventeen checks cannot say anything without an intake answer.
        Whether processing must stay inside the EU Data Boundary, whether
        unmanaged devices are controlled, how big the first pilot group is,
        whether there is an AI usage policy: none of that is visible in Graph,
        because it is a decision, not a setting. Unanswered, those checks
        report "not measured" -- never a false "in order".

        With no -Path this writes nothing and emits one object per question,
        so the whole questionnaire is a pipeline away:

            Get-RaidinessIntake | Where-Object Section -eq 'security' | Format-Table Key, Question

        With -Path it writes a file to fill in: JSON by default, or CSV, which
        is what an intake actually looks like in practice -- a spreadsheet on
        the table between you and the customer. Fill in the Answer column and
        hand it back to Set-RaidinessIntake.

    .PARAMETER Path
        File to write the questionnaire to. Omit to emit objects instead.

    .PARAMETER Format
        Json (default) or Csv.

    .PARAMETER From
        An earlier intake.json or run folder, to pre-fill the answers with.

    .PARAMETER Section
        Only these sections (repeatable), e.g. security, choice, pilot.

    .PARAMETER Force
        Overwrite an existing file.

    .EXAMPLE
        Get-RaidinessIntake -Path ./intake.csv -Format Csv
        # fill in the Answer column, then:
        Set-RaidinessIntake -RunPath ./raidiness/2026-09-02-1431 -FromFile ./intake.csv
    #>

    [CmdletBinding()]
    [OutputType([pscustomobject])]
    param(
        [string] $Path,
        [ValidateSet('Json', 'Csv')]
        [string] $Format = 'Json',
        [string] $From,
        [string[]] $Section,
        [switch] $Force
    )

    $ErrorActionPreference = 'Stop'

    $catalog = Read-RaidinessIntakeCatalog
    $questions = $catalog.Questions
    if ($Section) {
        $questions = @($questions | Where-Object { $_.Section -in $Section })
        if ($questions.Count -eq 0) {
            throw "No questions in section(s) $($Section -join ', '). Known sections: $(($catalog.Sections.key) -join ', ')."
        }
    }

    $existing = @{}
    if ($From) {
        foreach ($pair in (Read-RaidinessIntakeAnswer -Path $From).GetEnumerator()) {
            $existing[$pair.Key] = $pair.Value
        }
    }

    foreach ($question in $questions) {
        foreach ($key in @($question.Key) + $question.Aliases) {
            if ($existing.ContainsKey($key) -and $null -eq $question.Answer) {
                $question.Answer = $existing[$key]
            }
        }
    }

    if (-not $Path) { return $questions }

    if ((Test-Path -Path $Path) -and -not $Force) {
        throw "$Path already exists. Pass -Force to overwrite it."
    }

    if ($Format -eq 'Csv') {
        $questions |
            Select-Object @{ n = 'Key'; e = { $_.Key } },
            @{ n = 'Section'; e = { $_.SectionTitle } },
            @{ n = 'Question'; e = { $_.Question } },
            @{ n = 'Type'; e = { $_.Type } },
            @{ n = 'Options'; e = { $_.Options -join ' | ' } },
            @{ n = 'Answer'; e = { $_.Answer } } |
            Export-Csv -Path $Path -NoTypeInformation -Encoding utf8
    }
    else {
        $document = [ordered]@{
            raidinessIntake = [ordered]@{
                version     = '1.0'
                generatedAt = (Get-Date).ToUniversalTime().ToString('yyyy-MM-ddTHH:mm:ss.fffZ')
                note        = 'Fill in "answers". The "questions" list is regenerated on every Get-RaidinessIntake and ignored when read back.'
            }
            questions       = @($questions | ForEach-Object {
                    [ordered]@{
                        key      = $_.Key
                        section  = $_.SectionTitle
                        question = $_.Question
                        type     = $_.Type
                        options  = $_.Options
                    }
                })
            answers         = [ordered]@{}
        }
        foreach ($question in $questions) { $document.answers[$question.Key] = $question.Answer }
        ConvertTo-Json -InputObject $document -Depth 8 | Out-File -FilePath $Path -Encoding utf8
    }

    $answered = @($questions | Where-Object { $null -ne $_.Answer -and "$($_.Answer)".Trim() -ne '' }).Count
    Write-Host "Questionnaire written to $((Resolve-Path $Path).Path) — $($questions.Count) question(s), $answered answered." -ForegroundColor Green
    Write-Host 'Fill it in, then: Set-RaidinessIntake -RunPath <run folder> -FromFile <this file>' -ForegroundColor Cyan
}