scripts/workflow-add.ps1

#!/usr/bin/env pwsh
<#
.SYNOPSIS
    Add a workflow to an existing dotbot project.

.PARAMETER Name
    Workflow identifier (e.g., "iwg:iwg-bs-scoring" for registry or "my-workflow" for built-in).

.PARAMETER Force
    Overwrite if already installed.
#>

param(
    [Parameter(Position = 0)]
    [string]$Name,
    [switch]$Force
)

$ErrorActionPreference = "Stop"

$DotbotBase = Join-Path $HOME "dotbot"
$ProjectDir = Get-Location
$BotDir = Join-Path $ProjectDir ".bot"

Import-Module (Join-Path $DotbotBase "scripts\Platform-Functions.psm1") -Force

if (-not (Test-Path $BotDir)) {
    Write-DotbotError "No .bot directory found. Run 'dotbot init' first."
    exit 1
}

if (-not $Name) {
    Write-DotbotWarning "Usage: dotbot workflow add <name>"
    Write-DotbotCommand "Example: dotbot workflow add iwg:iwg-bs-scoring"
    exit 1
}

# Import manifest utilities
. (Join-Path $BotDir "systems\runtime\modules\workflow-manifest.ps1")

$workflowsDir = Join-Path $BotDir "workflows"
if (-not (Test-Path $workflowsDir)) {
    New-Item -Path $workflowsDir -ItemType Directory -Force | Out-Null
}

# Resolve source directory
$wfSourceDir = $null
if ($Name -match '^([^:]+):(.+)$') {
    $namespace = $Matches[1]
    $wfShortName = $Matches[2]
    $candidate = Join-Path $DotbotBase "registries\$namespace\workflows\$wfShortName"
    if (Test-Path $candidate) { $wfSourceDir = $candidate }
    $displayName = $wfShortName
} else {
    $candidate = Join-Path $DotbotBase "workflows\$Name"
    if (Test-Path $candidate) { $wfSourceDir = $candidate }
    $displayName = $Name
}

if (-not $wfSourceDir) {
    Write-DotbotError "Workflow not found: $Name"
    exit 1
}

$wfTargetDir = Join-Path $workflowsDir $displayName
if ((Test-Path $wfTargetDir) -and -not $Force) {
    Write-DotbotWarning "Workflow '$displayName' already installed. Use --Force to overwrite."
    exit 1
}
if ((Test-Path $wfTargetDir) -and $Force) {
    Remove-Item $wfTargetDir -Recurse -Force
}

Write-Status "Installing workflow: $displayName"

# Copy files
New-Item -Path $wfTargetDir -ItemType Directory -Force | Out-Null
$wfSourceDirFull = [System.IO.Path]::GetFullPath($wfSourceDir)
Get-ChildItem -Path $wfSourceDir -Recurse -File | ForEach-Object {
    $relativePath = [System.IO.Path]::GetRelativePath($wfSourceDirFull, $_.FullName)
    $relativePathKey = $relativePath -replace '\\', '/'
    if ($relativePathKey -eq "on-install.ps1") { return }
    if ($relativePathKey -eq "manifest.yaml") { return }
    if ($relativePathKey -match '^systems/mcp/tools/(.+)$') { $relativePath = "tools/$($Matches[1])" }
    if ($relativePathKey -eq "settings/settings.default.json") { $relativePath = "settings.json" }

    $destPath = Join-Path $wfTargetDir $relativePath
    $destDir = Split-Path $destPath -Parent
    if (-not (Test-Path $destDir)) { New-Item -ItemType Directory -Path $destDir -Force | Out-Null }
    Copy-Item -Path $_.FullName -Destination $destPath -Force
}

# Copy workflow.yaml
$wfYamlSource = Join-Path $wfSourceDir "workflow.yaml"
$wfYamlTarget = Join-Path $wfTargetDir "workflow.yaml"
if (Test-Path $wfYamlSource) {
    Copy-Item $wfYamlSource $wfYamlTarget -Force
} elseif (-not (Test-Path $wfYamlTarget)) {
    $manifestYaml = Join-Path $wfSourceDir "manifest.yaml"
    if (Test-Path $manifestYaml) { Copy-Item $manifestYaml $wfYamlTarget -Force }
}

# Parse manifest
$manifest = Read-WorkflowManifest -WorkflowDir $wfTargetDir

# Scaffold .env.local
$envVars = @()
if ($manifest.requires -and $manifest.requires.env_vars) { $envVars = @($manifest.requires.env_vars) }
elseif ($manifest.requires -and $manifest.requires['env_vars']) { $envVars = @($manifest.requires['env_vars']) }
if ($envVars.Count -gt 0) {
    New-EnvLocalScaffold -EnvLocalPath (Join-Path $ProjectDir ".env.local") -EnvVars $envVars
}

# Merge MCP servers
if ($manifest.mcp_servers) {
    $added = Merge-McpServers -McpJsonPath (Join-Path $ProjectDir ".mcp.json") -WorkflowServers $manifest.mcp_servers
    if ($added -gt 0) { Write-DotbotCommand "Merged $added MCP server(s) into .mcp.json" }
}

# Update installed_workflows list + merge domain.task_categories from manifest
$settingsPath = Join-Path $BotDir "settings\settings.default.json"
if (Test-Path $settingsPath) {
    $settings = Get-Content $settingsPath -Raw | ConvertFrom-Json
    $existing = @()
    if ($settings.PSObject.Properties['installed_workflows']) { $existing = @($settings.installed_workflows) }
    if ($displayName -notin $existing) { $existing += $displayName }
    $settings | Add-Member -NotePropertyName "installed_workflows" -NotePropertyValue $existing -Force

    # Merge custom task_categories from workflow manifest domain section
    if ($manifest.domain -and $manifest.domain['task_categories']) {
        $wfCategories = @($manifest.domain['task_categories'])
        $currentCategories = @()
        if ($settings.PSObject.Properties['task_categories']) { $currentCategories = @($settings.task_categories) }
        $merged = @($currentCategories + $wfCategories | Select-Object -Unique)
        $settings | Add-Member -NotePropertyName "task_categories" -NotePropertyValue $merged -Force
    }

    $settings | ConvertTo-Json -Depth 10 | Set-Content $settingsPath
}

Write-Success "Workflow '$displayName' installed to .bot/workflows/$displayName/"