From 719e34951a444932f26012e803f8426cbe17b493 Mon Sep 17 00:00:00 2001 From: toolate28 Date: Thu, 20 Aug 2026 14:44:26 +0000 Subject: [PATCH] fix(tw): emit logos-bridge in next: slot, lint prose out MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ATOM-CLAUDE-LABEL-TW-NEXTLINE-20260820 The next: panel mixed paste-able commands with English. At 96.1% it printed "Optional: start reson8 styx WS bridge on :8088". PowerShell parses start as Start-Process and fails on WS. - bridge fix string -> logos-bridge (already declared in LogOS.Shell) - other non-command fix strings comment-prefixed - Test-NextActionRunnable + Assert-NextActionsRunnable so a prose line fails here, not at the operator - ops/tests/Test-TwNextActions.ps1 is the build gate Checked by: claude/reason (holds the label, not the fix — R4) --- ops/TriWeavon.Unitary.Profile.psm1 | 44 +++++++++++++++++++++++++----- ops/tests/Test-TwNextActions.ps1 | 40 +++++++++++++++++++++++++++ 2 files changed, 77 insertions(+), 7 deletions(-) create mode 100644 ops/tests/Test-TwNextActions.ps1 diff --git a/ops/TriWeavon.Unitary.Profile.psm1 b/ops/TriWeavon.Unitary.Profile.psm1 index f3c2653..e6731a8 100644 --- a/ops/TriWeavon.Unitary.Profile.psm1 +++ b/ops/TriWeavon.Unitary.Profile.psm1 @@ -17,7 +17,7 @@ Set-StrictMode -Version Latest -$script:UnitaryVersion = '1.1.1-unitary' +$script:UnitaryVersion = '1.1.2-unitary' $script:SensorCache = $null $script:SensorCacheAt = [datetime]::MinValue $script:SensorTtlSec = 6 @@ -147,6 +147,33 @@ function Get-ShadeBar { return ('█' * $n) + ('░' * ($Width - $n)) } + +function Test-NextActionRunnable { + <# + .SYNOPSIS + ATOM-CLAUDE-LABEL-TW-NEXTLINE-20260820 + A next: line is paste-able iff it is a resolvable command or comment-prefixed. + Prose in a command slot must fail here, not reach the operator. + #> + [CmdletBinding()] + param([Parameter(Mandatory)][AllowEmptyString()][string]$Line) + $item = ($Line -replace '^\d+\.\s*', '').Trim() + if (-not $item) { return $true } + if ($item.StartsWith('#')) { return $true } + $payload = ($item -split '#', 2)[0].Trim() + return [bool]($payload -match '^(tw|logos-[a-z-]+|cargo|docker|python|pwsh|cd|git|npm|node)\b') +} + +function Assert-NextActionsRunnable { + param([string[]]$Actions) + foreach ($a in @($Actions)) { + if ($null -eq $a -or "$a" -eq '') { continue } + if (-not (Test-NextActionRunnable -Line "$a")) { + throw "tw next: prose in a command slot: $a — emit a resolvable command or prefix with #" + } + } +} + # ─── Sensor board ──────────────────────────────────────────────────────────── function Get-TriWeavonSensors { @@ -171,7 +198,7 @@ function Get-TriWeavonSensors { $s.logos_root = [pscustomobject]@{ name = 'logos_root'; ok = [bool]$root; critical = $true detail = if ($root) { $root } else { 'MISSING — set LOGOS_ROOT' } - fix = if (-not $root) { 'Set LOGOS_ROOT=%USERPROFILE%\LogOS (or your clone path)' } else { $null } + fix = if (-not $root) { '# Set LOGOS_ROOT=%USERPROFILE%\LogOS (or your clone path)' } else { $null } shade = Get-ShadeBar $(if ($root) { 1 } else { 0 }) } @@ -179,7 +206,7 @@ function Get-TriWeavonSensors { $s.wsl = [pscustomobject]@{ name = 'wsl'; ok = [bool]$wsl; critical = $true detail = if ($wsl) { $wsl } else { 'no distro' } - fix = if (-not $wsl) { 'Install/start WSL Kali (build substrate)' } else { $null } + fix = if (-not $wsl) { '# Install/start WSL Kali (build substrate)' } else { $null } shade = Get-ShadeBar $(if ($wsl) { 1 } else { 0 }) } @@ -219,7 +246,7 @@ function Get-TriWeavonSensors { $s.bridge = [pscustomobject]@{ name = 'bridge'; ok = $br; critical = $false detail = if ($br) { 'ws://127.0.0.1:8088' } else { 'down — optional SPHINX WS' } - fix = if (-not $br) { 'Optional: start reson8 styx WS bridge on :8088' } else { $null } + fix = if (-not $br) { 'logos-bridge' } else { $null } shade = Get-ShadeBar $(if ($br) { 0.9 } else { 0.15 }) } @@ -235,7 +262,7 @@ function Get-TriWeavonSensors { $s.docker = [pscustomobject]@{ name = 'docker'; ok = ($dockerHost -or $dockerWsl); critical = $false detail = if ($dockerHost) { 'host CLI' } elseif ($dockerWsl) { "WSL/$wsl" } else { 'absent' } - fix = if (-not ($dockerHost -or $dockerWsl)) { 'Start Docker Desktop or dockerd in WSL' } else { $null } + fix = if (-not ($dockerHost -or $dockerWsl)) { '# Start Docker Desktop or dockerd in WSL' } else { $null } shade = Get-ShadeBar $(if ($dockerHost -or $dockerWsl) { 0.9 } else { 0.1 }) } @@ -250,7 +277,7 @@ function Get-TriWeavonSensors { $s.schemas = [pscustomobject]@{ name = 'schemas'; ok = $schemaOk; critical = $true detail = if ($schemaOk) { 'v0.1 filed' } else { 'schemas missing' } - fix = if (-not $schemaOk) { 'Pull LogOS; ensure docs/schemas/v0.1 exists' } else { $null } + fix = if (-not $schemaOk) { '# Pull LogOS; ensure docs/schemas/v0.1 exists' } else { $null } shade = Get-ShadeBar $(if ($schemaOk) { 1 } else { 0 }) } @@ -269,6 +296,7 @@ function Get-TriWeavonSensors { $down = @($s.Values | Where-Object { -not $_.ok }) $actions = @($down | Where-Object { $_.fix } | ForEach-Object { $_.fix } | Select-Object -First 5) + Assert-NextActionsRunnable $actions $board = [pscustomobject]@{ timestamp = $now.ToString('o') @@ -751,5 +779,7 @@ Export-ModuleMember -Function @( 'Invoke-TriWeavonTw', 'Start-TriWeavonUnitary', 'Get-ShadeBar', - 'Test-TcpPortFast' + 'Test-TcpPortFast', + 'Test-NextActionRunnable', + 'Assert-NextActionsRunnable' ) -Alias @('tw', 'tw-sensors', 'tw-health', 'tw-fix', 'tw-up', 'tw-verify', 'tw-help', 'tw-confidence') diff --git a/ops/tests/Test-TwNextActions.ps1 b/ops/tests/Test-TwNextActions.ps1 new file mode 100644 index 0000000..65b4661 --- /dev/null +++ b/ops/tests/Test-TwNextActions.ps1 @@ -0,0 +1,40 @@ +# ATOM-CLAUDE-LABEL-TW-NEXTLINE-20260820 +# Fail the build if tw next: would print prose in a command slot. +# Checked by claude/reason. Owner: grok/build. + +$ErrorActionPreference = 'Stop' +$here = Split-Path -Parent $MyInvocation.MyCommand.Path +$mod = Join-Path (Split-Path -Parent $here) 'TriWeavon.Unitary.Profile.psm1' +if (-not (Test-Path -LiteralPath $mod)) { + $mod = Join-Path $PSScriptRoot '../TriWeavon.Unitary.Profile.psm1' +} +Import-Module $mod -Force + +$pass = 0; $fail = 0 +function Expect($line, $ok) { + $got = Test-NextActionRunnable -Line $line + if ($got -eq $ok) { + Write-Host " PASS ok=$ok $line" -ForegroundColor Green + $script:pass++ + } else { + Write-Host " FAIL expected ok=$ok got=$got $line" -ForegroundColor Red + $script:fail++ + } +} + +Expect 'logos-bridge' $true +Expect 'tw up waist # or WSL: cd "$LOGOS_ROOT" && docker compose up -d' $true +Expect 'tw up bbbr # python hup/unikernel/bbbr-verifier/bbbr_unix.py (:8081)' $true +Expect 'tw up styx # cargo run -p styx-vfs-layer --bin styx-bookshelf' $true +Expect '# Set LOGOS_ROOT=%USERPROFILE%\LogOS (or your clone path)' $true +Expect '# Install/start WSL Kali (build substrate)' $true +Expect '# Start Docker Desktop or dockerd in WSL' $true +Expect '# Pull LogOS; ensure docs/schemas/v0.1 exists' $true +Expect 'Optional: start reson8 styx WS bridge on :8088' $false +Expect 'Set LOGOS_ROOT=%USERPROFILE%\LogOS (or your clone path)' $false +Expect '' $true +Expect '# comment only' $true + +Write-Host (" result: {0} pass / {1} fail" -f $pass, $fail) +if ($fail -gt 0) { exit 1 } +exit 0