scripts/init/post-bootstrap-output.ps1

# Post-bootstrap output helpers for specrew-init.ps1 (extracted via Proposal 108 Slice 8)
#
# Depends on: scripts/init/_utilities.ps1 (Get-SpecrewExecutionLayout)
#
# Functions:
# - Write-PostBootstrapGuidance 130-line bootstrap-success splash (greeting, usage flow, next steps,
# slash-command surface, team extension instructions, PATH guidance)
# - Write-BootstrapSummary final action-table summary (single-line outcomes per step)
#
# Host-coupling notes (Phase D / Slice 9+ follow-up):
# Write-PostBootstrapGuidance is now Crew-generic — "the Crew" instead of "Squad" — since F-044
# Slice 9 ships per-host Crew runtimes for Claude, Codex, and Antigravity in addition to Copilot.
# Host-specific runtime paths (.squad/team.md customization, /specrew-* surface availability per
# host) remain Copilot-default at init time; per-host runtime team customization is queued behind
# the `specrew team` CLI rewire follow-up (see specs/044-per-host-architecture-refactor/spec.md).

Set-StrictMode -Version Latest

function Write-SpecrewBootstrapBaselineRecord {
    param(
        [Parameter(Mandatory = $true)]
        [string]$ProjectPath,

        [Parameter(Mandatory = $true)]
        [ValidateSet('automatic', 'offered', 'declined')]
        [string]$Decision
    )

    $specrewRoot = Join-Path $ProjectPath '.specrew'
    if (-not (Test-Path -LiteralPath $specrewRoot -PathType Container)) {
        $null = New-Item -ItemType Directory -Path $specrewRoot -Force
    }

    $recordPath = Join-Path $specrewRoot 'bootstrap-baseline.json'
    $record = [ordered]@{
        schema_version = '1.0'
        mode = if ($Decision -eq 'automatic') { 'greenfield' } else { 'brownfield' }
        decision = $Decision
        commit_message = 'chore(specrew): bootstrap scaffold'
        recorded_at = [DateTime]::UtcNow.ToString('o')
    }
    $json = $record | ConvertTo-Json -Depth 4
    $temporaryPath = '{0}.{1}.tmp' -f $recordPath, [Guid]::NewGuid().ToString('N')
    [System.IO.File]::WriteAllText($temporaryPath, ($json + [Environment]::NewLine), [System.Text.UTF8Encoding]::new($false))
    Move-Item -LiteralPath $temporaryPath -Destination $recordPath -Force
    return $recordPath
}

function Invoke-SpecrewBootstrapBaseline {
    param(
        [Parameter(Mandatory = $true)]
        [string]$ProjectPath,

        [Parameter(Mandatory = $true)]
        [ValidateSet('greenfield', 'brownfield')]
        [string]$BootstrapMode,

        [Parameter(Mandatory = $true)]
        [ValidateSet('offer', 'decline')]
        [string]$BrownfieldDecision,

        [AllowEmptyCollection()]
        [Parameter(Mandatory = $true)]
        [System.Collections.ArrayList]$Actions,

        [Parameter(Mandatory = $true)]
        [switch]$PreviewOnly
    )

    $commitMessage = 'chore(specrew): bootstrap scaffold'
    $recordPath = Join-Path $ProjectPath '.specrew\bootstrap-baseline.json'
    $existingDecision = $null
    if (Test-Path -LiteralPath $recordPath -PathType Leaf) {
        try {
            $existingRecord = Get-Content -LiteralPath $recordPath -Raw -Encoding UTF8 | ConvertFrom-Json -ErrorAction Stop
            $existingDecision = [string]$existingRecord.decision
        }
        catch {
            throw "Bootstrap baseline record is malformed: '$recordPath'."
        }
    }

    if ($existingDecision -eq 'automatic') {
        Add-Action -Actions $Actions -Step 'bootstrap-commit' -Outcome 'preserved recorded greenfield bootstrap baseline'
        return [pscustomobject]@{ Mode = 'greenfield'; Decision = 'automatic'; Commit = $null; RecordPath = $recordPath }
    }

    if ($BootstrapMode -eq 'brownfield') {
        $decision = if ($existingDecision -eq 'declined' -and $BrownfieldDecision -eq 'offer') { 'declined' } elseif ($BrownfieldDecision -eq 'decline') { 'declined' } else { 'offered' }
        if ($PreviewOnly) {
            Add-Action -Actions $Actions -Step 'bootstrap-commit' -Outcome ("would record brownfield bootstrap-commit {0}; no commit would be created" -f $decision)
            return [pscustomobject]@{ Mode = 'brownfield'; Decision = $decision; Commit = $null; RecordPath = $recordPath }
        }

        $recordPath = Write-SpecrewBootstrapBaselineRecord -ProjectPath $ProjectPath -Decision $decision
        if ($decision -eq 'declined') {
            Write-Host ("Brownfield bootstrap commit declined and recorded at {0}; no commit was created." -f $recordPath) -ForegroundColor Yellow
        }
        else {
            Write-Host 'Brownfield repository detected; Specrew did not create a surprise commit.' -ForegroundColor Yellow
            Write-Host ("Bootstrap commit offer recorded at {0}. Review 'git status', stage the scaffold you accept, then commit it as '{1}'. To record a decline, rerun init with --brownfield-bootstrap-commit decline." -f $recordPath, $commitMessage) -ForegroundColor Yellow
        }
        Add-Action -Actions $Actions -Step 'bootstrap-commit' -Outcome ("brownfield {0}; no commit created; record={1}" -f $decision, $recordPath)
        return [pscustomobject]@{ Mode = 'brownfield'; Decision = $decision; Commit = $null; RecordPath = $recordPath }
    }

    if ($PreviewOnly) {
        Add-Action -Actions $Actions -Step 'bootstrap-commit' -Outcome ("would create and announce greenfield commit '{0}'" -f $commitMessage)
        return [pscustomobject]@{ Mode = 'greenfield'; Decision = 'automatic'; Commit = $null; RecordPath = $recordPath }
    }

    $insideWorkTree = @(& git -C $ProjectPath rev-parse --is-inside-work-tree 2>$null)
    if ($LASTEXITCODE -ne 0 -or ($insideWorkTree -join '').Trim() -ne 'true') {
        $null = & git -C $ProjectPath init --quiet 2>&1
        if ($LASTEXITCODE -ne 0) {
            throw "Greenfield bootstrap completed, but Git repository initialization failed for '$ProjectPath'."
        }
    }

    $createdRecord = $false
    try {
        $recordPath = Write-SpecrewBootstrapBaselineRecord -ProjectPath $ProjectPath -Decision 'automatic'
        $createdRecord = $true
        $addOutput = @(& git -C $ProjectPath add --all 2>&1)
        if ($LASTEXITCODE -ne 0) {
            throw ("Greenfield bootstrap staging failed: {0}" -f ($addOutput -join [Environment]::NewLine))
        }

        $configuredUserName = (@(& git -C $ProjectPath config --get user.name 2>$null) | Select-Object -First 1)
        $configuredUserEmail = (@(& git -C $ProjectPath config --get user.email 2>$null) | Select-Object -First 1)
        $identityArguments = @()
        if ([string]::IsNullOrWhiteSpace($configuredUserName) -or [string]::IsNullOrWhiteSpace($configuredUserEmail)) {
            # Keep the bootstrap reliable on brand-new machines and CI without mutating global or local Git config.
            # A configured user identity always wins; this command-scoped identity is only the no-config fallback.
            $identityArguments = @('-c', 'user.name=Specrew Bootstrap', '-c', 'user.email=specrew-bootstrap@example.invalid')
        }
        $commitOutput = @(& git -C $ProjectPath @identityArguments commit --quiet -m $commitMessage 2>&1)
        if ($LASTEXITCODE -ne 0) {
            throw ("Greenfield bootstrap commit failed: {0}" -f ($commitOutput -join [Environment]::NewLine))
        }

        $commit = (@(& git -C $ProjectPath rev-parse HEAD 2>&1) | Select-Object -First 1).Trim()
        if ($LASTEXITCODE -ne 0 -or $commit -notmatch '^[0-9a-f]{40}$') {
            throw 'Greenfield bootstrap commit was created, but its full Git identity could not be resolved.'
        }

        Write-Host ("Created bootstrap commit {0}: {1}" -f $commit, $commitMessage) -ForegroundColor Green
        Add-Action -Actions $Actions -Step 'bootstrap-commit' -Outcome ("created and announced {0}: {1}" -f $commit, $commitMessage)
        return [pscustomobject]@{ Mode = 'greenfield'; Decision = 'automatic'; Commit = $commit; RecordPath = $recordPath }
    }
    catch {
        $null = & git -C $ProjectPath rm --cached -r --ignore-unmatch . 2>$null
        if ($createdRecord -and (Test-Path -LiteralPath $recordPath -PathType Leaf)) {
            Remove-Item -LiteralPath $recordPath -Force -ErrorAction SilentlyContinue
        }
        throw
    }
}

function Write-PostBootstrapGuidance {
    param(
        [Parameter(Mandatory = $true)]
        [string]$ProjectPath
    )

    $baselineRoles = 'Spec Steward, Planner, Implementer, Reviewer, Retro Facilitator'
    $canonicalTeamPath = Join-Path $ProjectPath '.specrew\team\agents\'
    # Use the execution layout's scripts dir (one level below RootPath), NOT $PSScriptRoot.
    # After Slice 8, $PSScriptRoot here is scripts/init/, but the PATH guidance must point to
    # scripts/ (where specrew.ps1 lives). Resolve from the layout to stay location-independent.
    $executionLayout = Get-SpecrewExecutionLayout
    $isModuleContext = ($executionLayout.Mode -eq 'module')
    $specrewScriptsPath = Join-Path $executionLayout.RootPath 'scripts'

    Write-Host ''
    Write-Host ' ╱─────────────────╲' -ForegroundColor Cyan
    Write-Host ' ╱ ●━━●━━● ╲' -ForegroundColor Cyan
    Write-Host ' │ ╲ │' -ForegroundColor Cyan
    Write-Host ' │ ●━━●━━● │' -ForegroundColor Blue
    Write-Host ' │ ╲ │' -ForegroundColor Blue
    Write-Host ' ╲ ●━━●━━● ╱' -ForegroundColor Blue
    Write-Host ' ╲─────────────────╱' -ForegroundColor Blue
    Write-Host ''
    Write-Host ' S P E C R E W' -ForegroundColor White
    Write-Host ' ─── GOVERNED AGENTIC SDLC ───' -ForegroundColor DarkGray
    Write-Host ''
    Write-Host ' Bootstrap Complete' -ForegroundColor Green
    Write-Host ''
    Write-Host ("Baseline Specrew crew installed: {0}." -f $baselineRoles) -ForegroundColor White
    Write-Host ''
    Write-Host '=== Usage Flow ===' -ForegroundColor Cyan
    Write-Host ''
    Write-Host 'Baseline Crew → specrew start → the Crew drives specify → clarify for new specs (or recorded skip on resumed clarified work) → plan → tasks → implement → review → retro' -ForegroundColor Yellow
    Write-Host ''
    Write-Host '=== Next Steps ===' -ForegroundColor Cyan
    Write-Host ''
    Write-Host '1. Start spec authoring (Spec Kit workflows):' -ForegroundColor Yellow
    Write-Host ' - Run specrew start from the project root (optionally add a short feature request)' -ForegroundColor White
    Write-Host ' - Specrew launches the selected host CLI (default: Copilot; `--host claude`, `--host codex`, `--host antigravity`, or `--host cursor` available) from the project directory in the current terminal by default, stays out of autopilot until intake is grounded, and supports --new-window or --prompt-approvals when you want them' -ForegroundColor White
    Write-Host ' - Specrew hands off to the selected host CLI with full lifecycle context auto-loaded' -ForegroundColor White
    Write-Host ' - The Crew drives specify -> clarify -> plan -> tasks -> implement (skip clarify only for resumed clarified work with a recorded rationale)' -ForegroundColor White
    Write-Host ''
    Write-Host '2. Resuming work later:' -ForegroundColor Yellow
    Write-Host ' - Every later session also starts with specrew start from the project root' -ForegroundColor White
    Write-Host ' - specrew start regenerates the runtime handoff before launch' -ForegroundColor White
    Write-Host ' - Do not run the host CLI directly (e.g., `copilot ...` / `claude ...` / `codex ...`); going around `specrew start` skips the bootstrap refresh and leaves the launch contract stale' -ForegroundColor White
    Write-Host ''
    Write-Host '3. Run the iteration lifecycle:' -ForegroundColor Yellow
    Write-Host ' - Materialize iteration artifacts under specs/<feature>/iterations/<NNN>/' -ForegroundColor White
    Write-Host ' - Keep plan.md, state.md, drift-log.md, review.md, and retro.md current by phase' -ForegroundColor White
    Write-Host ' - Run validate-governance.ps1 before phase transitions' -ForegroundColor White
    Write-Host ''
    Write-Host 'Slash-command surface provisioned:' -ForegroundColor Green
    Write-Host ' - /specrew-where, /specrew-status, /specrew-update, /specrew-team, /specrew-review, /specrew-help, /specrew-version' -ForegroundColor White
    Write-Host ' - Deployed to .claude/skills/, .github/skills/, and .agents/skills/ with identical SKILL.md content' -ForegroundColor White
    Write-Host ' - If host-native /specrew- discovery is unavailable, use /specrew-help as the catalog fallback' -ForegroundColor White
    Write-Host ''
    Write-Host '4. (Optional) Add domain-specific team members:' -ForegroundColor Yellow
    Write-Host ' Add extra Crew members (Security Analyst, UX Designer, DBA, or other specialists)' -ForegroundColor White
    Write-Host ' using Specrew team management commands. Custom agents are stored at the canonical' -ForegroundColor White
    Write-Host (' location ({0}) and re-translated to each host' -f $canonicalTeamPath) -ForegroundColor White
    Write-Host ' on the next `specrew start`:' -ForegroundColor White
    Write-Host ''

    if ($isModuleContext) {
        Write-Host ' specrew team add <member-name> --role <role> --charter "<charter-text>"' -ForegroundColor White
        Write-Host ' specrew start' -ForegroundColor White
        Write-Host ' specrew team list' -ForegroundColor White
        Write-Host ' specrew team update <member-name> --charter "<new-charter>"' -ForegroundColor White
        Write-Host ' specrew team remove <member-name>' -ForegroundColor White
    } else {
        Write-Host ' pwsh -File <specrew-repo>/scripts/specrew.ps1 team add <member-name> --role <role> --charter "<charter-text>"' -ForegroundColor White
        Write-Host ' pwsh -File <specrew-repo>/scripts/specrew.ps1 start' -ForegroundColor White
        Write-Host ' pwsh -File <specrew-repo>/scripts/specrew.ps1 team list' -ForegroundColor White
        Write-Host ' pwsh -File <specrew-repo>/scripts/specrew.ps1 team update <member-name> --charter "<new-charter>"' -ForegroundColor White
        Write-Host ' pwsh -File <specrew-repo>/scripts/specrew.ps1 team remove <member-name>' -ForegroundColor White
    }

    Write-Host ''
    Write-Host (' Keep the Specrew-managed baseline charters intact under {0}.' -f $canonicalTeamPath) -ForegroundColor Yellow
    Write-Host ' (Generated host-native files under .squad/, .claude/, .codex/, .agents/ are re-synced' -ForegroundColor DarkGray
    Write-Host ' from canonical on every specrew start; delete the .specrew-managed sidecar to opt out.)' -ForegroundColor DarkGray
    Write-Host ''

    if (-not $isModuleContext) {
        Write-Host 'Replace <specrew-repo> with the actual path where you cloned Specrew.' -ForegroundColor Yellow
        Write-Host ''
        Write-Host '=== Optional: Add Specrew to PATH for Convenience ===' -ForegroundColor Cyan
        Write-Host ''
        Write-Host 'To use the short form (e.g., "specrew team list") instead of full paths,' -ForegroundColor White
        Write-Host 'you can add the scripts directory to your PATH.' -ForegroundColor White
        Write-Host ''

        if ($IsWindows) {
            Write-Host 'OPTION 1: Current Session Only (Windows)' -ForegroundColor Yellow
            Write-Host 'Run this command in your current PowerShell session:' -ForegroundColor White
            Write-Host ''
            Write-Host (' $env:PATH = "$env:PATH;{0}"' -f $specrewScriptsPath) -ForegroundColor Green
            Write-Host ''
            Write-Host '(This only affects the current shell and is lost when you close it.)' -ForegroundColor DarkGray
            Write-Host ''
            Write-Host 'OPTION 2: Persistent (All Future Sessions, Windows)' -ForegroundColor Yellow
            Write-Host 'To make this permanent for your user account, run:' -ForegroundColor White
            Write-Host ''
            Write-Host (' $currentPath = [Environment]::GetEnvironmentVariable("PATH", "User")') -ForegroundColor Green
            Write-Host (' $pathEntries = $currentPath -split "";""') -ForegroundColor Green
            Write-Host (' if ($pathEntries -notcontains ""{0}"") {{' -f $specrewScriptsPath) -ForegroundColor Green
            Write-Host (' [Environment]::SetEnvironmentVariable("PATH", "$currentPath;{0}", "User")' -f $specrewScriptsPath) -ForegroundColor Green
            Write-Host (' Write-Host "Added Specrew scripts to user PATH. Restart your shell to apply." -ForegroundColor Green') -ForegroundColor Green
            Write-Host (' }') -ForegroundColor Green
            Write-Host ''
            Write-Host '(This adds the path to your user-level environment and persists across sessions.' -ForegroundColor DarkGray
            Write-Host ' Restart your shell after running this command.)' -ForegroundColor DarkGray
        } elseif ($IsLinux -or $IsMacOS) {
            $shellProfile = if ($IsMacOS) { '~/.zshrc or ~/.bash_profile' } else { '~/.bashrc or ~/.profile' }
            Write-Host 'Adding Specrew to PATH (Linux/macOS)' -ForegroundColor Yellow
            Write-Host ('Add this line to your shell profile ({0}):' -f $shellProfile) -ForegroundColor White
            Write-Host ''
            Write-Host (' export PATH="$PATH:{0}"' -f $specrewScriptsPath) -ForegroundColor Green
            Write-Host ''
            Write-Host 'Then reload your shell:' -ForegroundColor White
            Write-Host ''
            Write-Host (' source {0}' -f $shellProfile) -ForegroundColor Green
            Write-Host ''
            Write-Host 'Or restart your terminal.' -ForegroundColor DarkGray
        }

        Write-Host ''
    }

    Write-Host '============================================================' -ForegroundColor Cyan
    Write-Host ''
    Write-Host 'Documentation:' -ForegroundColor White
    Write-Host ' - Getting Started: docs/getting-started.md' -ForegroundColor DarkGray
    Write-Host ' - User Guide: docs/user-guide.md' -ForegroundColor DarkGray
    Write-Host ''
}

function Write-BootstrapSummary {
    param(
        [AllowEmptyCollection()]
        [Parameter(Mandatory = $true)]
        [System.Collections.ArrayList]$Actions,

        [Parameter(Mandatory = $true)]
        [bool]$DryRunMode,

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

        [Parameter(Mandatory = $true)]
        [bool]$ShowGuidance
    )

    Write-Host ''
    Write-Host 'Bootstrap summary' -ForegroundColor Green
    $Actions | Format-Table -AutoSize

    if ($DryRunMode) {
        Write-Host 'Dry run complete. No files were changed.' -ForegroundColor Yellow
        return
    }

    Write-Host ("Bootstrap completed for {0}." -f $ProjectPath) -ForegroundColor Green
    if ($ShowGuidance) {
        Write-PostBootstrapGuidance -ProjectPath $ProjectPath
    }
}