param( [int]$Concurrency = 3 ) $ErrorActionPreference = "Stop" $repo = "D:\workspace\vignette" $bashExe = "C:\Program Files\Git\bin\bash.exe" $wrapper = "/c/Users/encep/.codex/imagegen-headless/codex_imagegen.sh" $runner = "/d/workspace/vignette/docs/design-concepts/prompts/run-one-imagegen.sh" $outDir = "/d/workspace/vignette/docs/design-concepts/generated" $promptDoc = Join-Path $repo "docs\design-concepts\prompts\vignette-design-prompts-2026-06-27.md" $runtimePromptDir = Join-Path $repo "docs\design-concepts\prompts\.runtime" $items = @( @{ Slug = "01-login-responsive" Out = "$outDir/01-login-responsive.png" }, @{ Slug = "02-learner-home-responsive" Out = "$outDir/02-learner-home-responsive.png" }, @{ Slug = "03-session-responsive" Out = "$outDir/03-session-responsive.png" }, @{ Slug = "04-session-review-responsive" Out = "$outDir/04-session-review-responsive.png" }, @{ Slug = "05-professor-responsive" Out = "$outDir/05-professor-responsive.png" }, @{ Slug = "06-admin-responsive" Out = "$outDir/06-admin-responsive.png" }, @{ Slug = "07-settings-responsive" Out = "$outDir/07-settings-responsive.png" }, @{ Slug = "08-warm-visual-elements" Out = "$outDir/08-warm-visual-elements.png" }, @{ Slug = "09-avatar-pattern-elements" Out = "$outDir/09-avatar-pattern-elements.png" } ) function Get-PromptBlock { param([string]$Slug) $raw = Get-Content -Raw -Encoding UTF8 -LiteralPath $promptDoc $pattern = "(?ms)^### $([regex]::Escape($Slug))\s*(.*?)(?=^### |\z)" $match = [regex]::Match($raw, $pattern) if (-not $match.Success) { throw "프롬프트 블록을 찾지 못함: $Slug" } return $match.Groups[1].Value.Trim() } New-Item -ItemType Directory -Force -Path (Join-Path $repo "docs\design-concepts\generated") | Out-Null New-Item -ItemType Directory -Force -Path $runtimePromptDir | Out-Null $queue = New-Object System.Collections.Queue foreach ($item in $items) { $queue.Enqueue($item) } $running = @() while ($queue.Count -gt 0 -or $running.Count -gt 0) { while ($queue.Count -gt 0 -and $running.Count -lt $Concurrency) { $item = $queue.Dequeue() $prompt = Get-PromptBlock -Slug $item.Slug $promptFileWin = Join-Path $runtimePromptDir "$($item.Slug).txt" $promptFileBash = "/d/workspace/vignette/docs/design-concepts/prompts/.runtime/$($item.Slug).txt" $utf8NoBom = New-Object System.Text.UTF8Encoding($false) [System.IO.File]::WriteAllText($promptFileWin, $prompt, $utf8NoBom) Write-Host "[imagegen] start $($item.Slug)" $job = Start-Job -Name $item.Slug -ScriptBlock { param($BashExe, $BashRunner, $BashWrapper, $OutPath, $PromptFile) $ErrorActionPreference = "Continue" & $BashExe $BashRunner $PromptFile $BashWrapper $OutPath if ($LASTEXITCODE -ne 0) { throw "imagegen failed: $OutPath" } } -ArgumentList $bashExe, $runner, $wrapper, $item.Out, $promptFileBash $running += $job } $done = Wait-Job -Job $running -Any -Timeout 15 if ($null -eq $done) { continue } foreach ($job in @($done)) { Receive-Job -Job $job if ($job.State -ne "Completed") { throw "이미지 생성 작업 실패: $($job.Name)" } Write-Host "[imagegen] done $($job.Name)" Remove-Job -Job $job $running = @($running | Where-Object { $_.Id -ne $job.Id }) } } Write-Host "[imagegen] all done"