From 90c09eea54e3081391bee51b915a0055ec7c9839 Mon Sep 17 00:00:00 2001 From: Copilot Date: Sun, 7 Jun 2026 12:26:29 -0700 Subject: [PATCH] fix(pull-sdlc): restore blank-line separators before WhatIf/up-to-date footers The output-stream refactor (#194) dropped two Write-Host '' separators when converting the footers to Write-Information, so the -WhatIf specified; no changes written. and Already up to date. lines printed flush against the planned-ops preview. Restore the separators as Write-Information '' (same stream as the footer so they suppress/redirect together). Not added to the preview helper or the apply path -- the Applied N ops. line never had a leading blank line. Closes #196 Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- Pull-SDLC.ai.Tests.ps1 | 43 ++++++++++++++++++++++++++++++++++++++---- Pull-SDLC.ai.ps1 | 2 ++ 2 files changed, 41 insertions(+), 4 deletions(-) diff --git a/Pull-SDLC.ai.Tests.ps1 b/Pull-SDLC.ai.Tests.ps1 index d16b581..962ce96 100644 --- a/Pull-SDLC.ai.Tests.ps1 +++ b/Pull-SDLC.ai.Tests.ps1 @@ -2713,8 +2713,43 @@ Describe 'Output stream assignment (issue #194)' { # Must be a genuine Write-Information record, NOT Write-Host (which tags PSHOST). $commitRec.Tags | Should -Not -Contain 'PSHOST' - $appliedRec = $streamInfo | Where-Object { "$($_.MessageData)" -match 'Applied 2 ops' } | Select-Object -First 1 - $appliedRec | Should -Not -BeNullOrEmpty - $appliedRec.Tags | Should -Not -Contain 'PSHOST' - } + $appliedRec = $streamInfo | Where-Object { "$($_.MessageData)" -match 'Applied 2 ops' } | Select-Object -First 1 + $appliedRec | Should -Not -BeNullOrEmpty + $appliedRec.Tags | Should -Not -Contain 'PSHOST' + } + + # --- Regression #196: blank-line separators dropped by the stream refactor --- + + It 'emits a blank-line separator immediately before the -WhatIf footer' { + $fx = New-DiffReplayFixture -Root $script:streamRoot ` + -Seed { New-Item -ItemType Directory -Path .github/agents -Force | Out-Null; 'one' | Out-File -Encoding utf8 .github/agents/a.md -NoNewline } ` + -Tweak { 'TWO' | Out-File -Encoding utf8 .github/agents/a.md -NoNewline } + Set-SdlcSyncState -RepoRoot $fx.Consumer -Remote 'sdlc.ai' -Ref 'main' -Commit $fx.AnchorSha + Push-Location $fx.Consumer + try { git add .sdlc-ai-sync.json; git commit -q -m 'seed state' } finally { Pop-Location } + + $rc = Invoke-PullSDLC -RepoRoot $fx.Consumer -RemoteName 'sdlc.ai' -NoFetch -WhatIf -InformationVariable streamInfo 6>$null + $rc | Should -Be 0 + + $msgs = @($streamInfo | ForEach-Object { "$($_.MessageData)" }) + $idx = [array]::IndexOf($msgs, '-WhatIf specified; no changes written.') + $idx | Should -BeGreaterThan 0 + $msgs[$idx - 1] | Should -Be '' + } + + It 'emits a blank-line separator immediately before the up-to-date footer' { + $fx = New-DiffReplayFixture -Root $script:streamRoot ` + -Seed { 'same' | Out-File -Encoding utf8 CLAUDE.md -NoNewline } + Set-SdlcSyncState -RepoRoot $fx.Consumer -Remote 'sdlc.ai' -Ref 'main' -Commit $fx.UpstreamHead + Push-Location $fx.Consumer + try { git add .sdlc-ai-sync.json; git commit -q -m 'seed state' } finally { Pop-Location } + + $rc = Invoke-PullSDLC -RepoRoot $fx.Consumer -RemoteName 'sdlc.ai' -NoFetch -InformationVariable streamInfo 6>$null + $rc | Should -Be 0 + + $msgs = @($streamInfo | ForEach-Object { "$($_.MessageData)" }) + $idx = [array]::IndexOf($msgs, 'Already up to date.') + $idx | Should -BeGreaterThan 0 + $msgs[$idx - 1] | Should -Be '' + } } diff --git a/Pull-SDLC.ai.ps1 b/Pull-SDLC.ai.ps1 index 360a379..4e64c19 100644 --- a/Pull-SDLC.ai.ps1 +++ b/Pull-SDLC.ai.ps1 @@ -2107,11 +2107,13 @@ function Invoke-PullSDLC { Write-PlannedOpsPreview -Ops $ops -AnchorLabel $anchorLabel -UpstreamLabel $upstreamLabel if ($WhatIfPreference) { + Write-Information '' Write-Information '-WhatIf specified; no changes written.' return 0 } if ($ops.Count -eq 0) { + Write-Information '' Write-Information 'Already up to date.' } else {