scripts/init/crew-bootstrap.ps1

# Crew-bootstrap dispatcher (Proposal 108 Slice 9)
#
# Single entry point for deploying the 5-agent Specrew Crew to a specific host's native location.
# Reads canonical charters from .specrew/team/agents/<role>.md and dispatches to each host's
# Install-<Kind>CrewRuntime contract function (in hosts/<kind>/handlers.ps1).
#
# Called by:
# - scripts/specrew-init.ps1 main flow (greenfield bootstrap for the default host)
# - scripts/specrew-start.ps1 (sync the selected host's view with canonical on every launch)
#
# Adding a new host = adding hosts/<new-kind>/handlers.ps1 with an Install-<NewKind>CrewRuntime function.
# This dispatcher picks it up automatically via Invoke-HostHandler.

Set-StrictMode -Version Latest

# Locate the host registry via a marker-file walk so this file is relocation-independent.
# The previous 2-level Split-Path was fragile if scripts/init/ moved relative to hosts/.
# Same lesson Slice 5/8 memorialized in _utilities.ps1::Get-SpecrewExecutionLayout.
$_crewBootstrapDistRoot = $PSScriptRoot
for ($_i = 0; $_i -lt 5; $_i++) {
    if (Test-Path -LiteralPath (Join-Path $_crewBootstrapDistRoot 'Specrew.psd1') -PathType Leaf) {
        break
    }
    $_crewBootstrapParent = Split-Path -Parent $_crewBootstrapDistRoot
    if ([string]::IsNullOrWhiteSpace($_crewBootstrapParent) -or $_crewBootstrapParent -eq $_crewBootstrapDistRoot) {
        break
    }
    $_crewBootstrapDistRoot = $_crewBootstrapParent
}
$_registryFromCrewBootstrap = Join-Path $_crewBootstrapDistRoot 'hosts\_registry.ps1'
if (Test-Path -LiteralPath $_registryFromCrewBootstrap -PathType Leaf) {
    . $_registryFromCrewBootstrap
}

function Initialize-SpecrewTeam {
    <#
    .SYNOPSIS
    Seed .specrew/team/agents/ from the shipped baseline charters (idempotent).
    Called on greenfield specrew init so the user has the canonical source-of-truth in place.
    .OUTPUTS
    pscustomobject @{ Actions[]; CanonicalRoot }
    #>

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

    if (-not (Get-Command Initialize-SpecrewTeamCanonical -ErrorAction SilentlyContinue)) {
        throw "Canonical-team helper not loaded (hosts/_team-canonical.ps1 missing or not dot-sourced)."
    }

    return (Initialize-SpecrewTeamCanonical -ProjectPath $ProjectPath -DryRun:$DryRun)
}

function Invoke-CrewBootstrap {
    <#
    .SYNOPSIS
    Deploy the Crew runtime to the specified host's native location by dispatching to
    hosts/<kind>/handlers.ps1::Install-<Kind>CrewRuntime via the host-package registry.
    .DESCRIPTION
    Idempotent + safe to call on every specrew start. Cheap (~50ms for 5-7 file translations).
    Translation source: .specrew/team/agents/<role>.md (canonical). Target: per-host AgentDir.
    .OUTPUTS
    Whatever the per-host Install-<Kind>CrewRuntime function returns (typically
    pscustomobject @{ Actions[]; CrewRuntimePath; Notices[] }).
    #>

    param(
        [Parameter(Mandatory = $true)][string]$ProjectPath,
        [Parameter(Mandatory = $true)][string]$HostKind,
        [switch]$DryRun
    )

    if (-not (Get-Command Invoke-HostHandler -ErrorAction SilentlyContinue)) {
        throw "Host registry not loaded. Ensure hosts/_registry.ps1 is dot-sourced before calling Invoke-CrewBootstrap."
    }

    # Auto-seed canonical .specrew/team/agents/ if missing. This makes `specrew start` work
    # on greenfield projects that never ran `specrew init`, AND keeps the "user edits canonical"
    # docs contract honest — the file actually appears after first start, ready for editing.
    if (Get-Command Get-SpecrewTeamAgentsPath -ErrorAction SilentlyContinue) {
        $_canonicalAgents = Get-SpecrewTeamAgentsPath -ProjectPath $ProjectPath
        if (-not (Test-Path -LiteralPath $_canonicalAgents -PathType Container) -and -not $DryRun) {
            if (Get-Command Initialize-SpecrewTeamCanonical -ErrorAction SilentlyContinue) {
                Initialize-SpecrewTeamCanonical -ProjectPath $ProjectPath | Out-Null
            }
        }
    }

    return Invoke-HostHandler -Kind $HostKind -ContractFunction InstallCrewRuntime -Arguments @{
        ProjectPath = $ProjectPath
        DryRun      = $DryRun
    }
}