diff --git a/scripts/run-void-moderator-rumination.ps1 b/scripts/run-void-moderator-rumination.ps1 index b01e427..a71ae5b 100644 --- a/scripts/run-void-moderator-rumination.ps1 +++ b/scripts/run-void-moderator-rumination.ps1 @@ -36,7 +36,7 @@ function Read-DotEnv { return $values } - foreach ($line in Get-Content -Path $Path) { + foreach ($line in Get-Content -Path $Path -Encoding UTF8) { if ([string]::IsNullOrWhiteSpace($line)) { continue } @@ -157,6 +157,9 @@ function Invoke-CodexExec { $startInfo.RedirectStandardOutput = $true $startInfo.RedirectStandardError = $true $startInfo.CreateNoWindow = $true + $utf8NoBom = [System.Text.UTF8Encoding]::new($false) + $startInfo.StandardOutputEncoding = $utf8NoBom + $startInfo.StandardErrorEncoding = $utf8NoBom $startInfo.Arguments = [string]::Join(" ", ($Arguments | ForEach-Object { Quote-ProcessArgument -Value $_ })) $process = [System.Diagnostics.Process]::new() @@ -164,8 +167,15 @@ function Invoke-CodexExec { try { [void]$process.Start() - $process.StandardInput.Write($InputText) - $process.StandardInput.Close() + $inputWriter = [System.IO.StreamWriter]::new($process.StandardInput.BaseStream, $utf8NoBom, 4096, $true) + + try { + $inputWriter.Write($InputText) + $inputWriter.Flush() + } finally { + $inputWriter.Dispose() + $process.StandardInput.Close() + } $stdoutTask = $process.StandardOutput.ReadToEndAsync() $stderrTask = $process.StandardError.ReadToEndAsync() @@ -226,7 +236,7 @@ trap { } if (Test-Path $lockPath) { - $lock = Get-Content -Path $lockPath -Raw | ConvertFrom-Json + $lock = Get-Content -Path $lockPath -Raw -Encoding UTF8 | ConvertFrom-Json $startedAt = $null if ($lock.startedAt) { @@ -462,7 +472,7 @@ if ($exitCode -eq 0) { $stateWriteAfter = (Get-Item $stateFilePath).LastWriteTimeUtc $stateUpdated = ($stateWriteAfter -gt $stateWriteBefore) -$lastMessage = if (Test-Path $lastMessagePath) { Get-Content -Path $lastMessagePath -Raw } else { "" } +$lastMessage = if (Test-Path $lastMessagePath) { Get-Content -Path $lastMessagePath -Raw -Encoding UTF8 } else { "" } Write-JsonFile -Path $statusPath -Data @{ status = if ($exitCode -eq 0) { "ok" } else { "failed" } diff --git a/state/evidence.jsonl b/state/evidence.jsonl index b130e41..ac3c0fd 100644 --- a/state/evidence.jsonl +++ b/state/evidence.jsonl @@ -65,3 +65,4 @@ {"ts":"2026-05-08T16:00:51Z","type":"architecture","status":"ok","note":"Manual moderation-state distillation showed the memory surface was overproducing near-duplicate repo-weather thoughts by storing each social flavor of the same seam as a separate semantic card, sweep, and synthesis. Periodic cleanup should merge those variants by conceptual family, rebalance recent source traces, and clear stale resonance/incubation caches so novelty pressure can regrow from a cleaner substrate."} {"ts":"2026-05-08T16:06:43Z","type":"architecture","status":"ok","note":"Quiet-room moderation no longer treats retrieval as compulsory ritual. If incubation already holds a live, grounded, low-saturation thought, Void may deepen it directly; archive dives and repo sweeps are now explicit support for hungry, stale, or oversaturated queues rather than mandatory throat-clearing before every private thought."} {"ts":"2026-05-08T19:39:40Z","type":"implementation","status":"ok","note":"Discord bot token health checks can hit Discord API rate limits even when the token is fine. The watchdog now distinguishes HTTP 429 from actual credential failures, downgrading rate limits to a warning with retry-after data instead of reporting a dead token."} +{"ts":"2026-05-09T18:08:46Z","type":"implementation","status":"ok","note":"Moderation rumination mojibake came from UTF-8 boundaries in the PowerShell runner, not corrupted canonical state. Explicitly decode redirected Codex stdout/stderr as UTF-8, read the saved final-message file as UTF-8, and write stdin through a UTF-8 StreamWriter for Windows PowerShell 5.1 compatibility."}