Skip to content

Commit 5f926a9

Browse files
committed
Add command logging and test foundation
1 parent 73f968b commit 5f926a9

20 files changed

Lines changed: 1064 additions & 108 deletions

.gitignore

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,9 @@
33
/obj/
44
/src/**/bin/
55
/src/**/obj/
6+
/tests/**/bin/
7+
/tests/**/obj/
8+
/tests/**/TestResults/
69
/decompiled/bin/
710
/decompiled/obj/
811

XeCLI.sln

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
21
Microsoft Visual Studio Solution File, Format Version 12.00
32
# Visual Studio Version 17
43
VisualStudioVersion = 17.13.35931.197
@@ -9,6 +8,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Xbox360.Remote.Cli", "src\\
98
EndProject
109
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Xbox360.Fatx", "src\\Xbox360.Fatx\\Xbox360.Fatx.csproj", "{A2C2BF7E-BA9E-4FD4-B624-38646E4C8140}"
1110
EndProject
11+
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "XeCLI.Tests", "tests\\XeCLI.Tests\\XeCLI.Tests.csproj", "{44CA1A12-446A-48AB-B5FF-C801BA7BDFCF}"
12+
EndProject
1213
Global
1314
GlobalSection(SolutionConfigurationPlatforms) = preSolution
1415
Debug|Any CPU = Debug|Any CPU
@@ -27,5 +28,9 @@ Global
2728
{A2C2BF7E-BA9E-4FD4-B624-38646E4C8140}.Debug|Any CPU.Build.0 = Debug|Any CPU
2829
{A2C2BF7E-BA9E-4FD4-B624-38646E4C8140}.Release|Any CPU.ActiveCfg = Release|Any CPU
2930
{A2C2BF7E-BA9E-4FD4-B624-38646E4C8140}.Release|Any CPU.Build.0 = Release|Any CPU
31+
{44CA1A12-446A-48AB-B5FF-C801BA7BDFCF}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
32+
{44CA1A12-446A-48AB-B5FF-C801BA7BDFCF}.Debug|Any CPU.Build.0 = Debug|Any CPU
33+
{44CA1A12-446A-48AB-B5FF-C801BA7BDFCF}.Release|Any CPU.ActiveCfg = Release|Any CPU
34+
{44CA1A12-446A-48AB-B5FF-C801BA7BDFCF}.Release|Any CPU.Build.0 = Release|Any CPU
3035
EndGlobalSection
3136
EndGlobal

docs/gui-visual-proof.md

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -30,9 +30,15 @@ The proof must confirm that state text matches the live console state.
3030

3131
Check these strings against the actual UI state:
3232

33-
- `Not connected`
34-
- `Connecting`
35-
- `Connected`
33+
- `DISCONNECTED`
34+
- `CONNECTING`
35+
- `CONNECTED`
36+
37+
Check link state labels against the actual UI state:
38+
39+
- `LINK OFFLINE`
40+
- `LINK ACTIVE`
41+
- `NOT CONNECTED`
3642

3743
Do not accept a screenshot if the text reads as one state while the session is actually another.
3844

@@ -42,6 +48,7 @@ Do not accept a screenshot if the text reads as one state while the session is a
4248
- Keep the window size and scaling stable during the run.
4349
- Do not crop away the parts that show current state, console target, or connection status.
4450
- Build contact sheets so reviewers can scan the whole set quickly.
51+
- Keep raw screenshots local unless the run has been separately redacted for publication.
4552

4653
## OCR Rules
4754

@@ -71,5 +78,10 @@ Before anything leaves the local machine:
7178
- redact local paths when they reveal private machine layout
7279
- redact tokens, keys, and live network details
7380

74-
Keep raw screenshots and OCR text local unless the run is being used as private proof for the current task.
81+
`scripts/run-visual-proof.ps1 -RedactText` writes `*-redacted` wrapper outputs with IPs and local paths masked in text fields, plus redacted copies of the smoke `report.md` and `summary.json` artifacts.
7582

83+
`scripts/run-visual-proof.ps1 -RedactText` writes `*-redacted` wrapper artifacts, and the contact-sheet builder pixel-masks common text zones in thumbnails while still redacting the generated JSON labels.
84+
85+
`scripts/build-contact-sheets.ps1 -RedactText` applies the same pixel masking when the sheet builder is run directly. Without `-RedactText`, the PNG contact sheet remains local-only proof.
86+
87+
Keep raw screenshots and OCR text local unless the run is being used as private proof for the current task.

scripts/build-contact-sheets.ps1

Lines changed: 84 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,8 @@ param(
55
[string]$Out,
66
[int]$Columns = 2,
77
[int]$ThumbWidth = 480,
8-
[int]$ThumbHeight = 270
8+
[int]$ThumbHeight = 270,
9+
[switch]$RedactText
910
)
1011

1112
$ErrorActionPreference = "Stop"
@@ -37,6 +38,41 @@ function Get-RelativeDisplayPath {
3738
return [System.IO.Path]::GetFileName($full)
3839
}
3940

41+
function Get-DisplayPath {
42+
param(
43+
[string]$Path
44+
)
45+
46+
if (-not $RedactText) {
47+
return $Path
48+
}
49+
50+
return Redact-Text (Get-RelativeDisplayPath -BasePath $repoRoot -Path $Path)
51+
}
52+
53+
function Redact-Text {
54+
param(
55+
[string]$Text
56+
)
57+
58+
if ([string]::IsNullOrEmpty($Text)) {
59+
return $Text
60+
}
61+
62+
$redacted = [regex]::Replace(
63+
$Text,
64+
'(?<!\d)(?:25[0-5]|2[0-4]\d|1?\d?\d)(?:\.(?:25[0-5]|2[0-4]\d|1?\d?\d)){3}(?!\d)',
65+
'<redacted-ipv4>'
66+
)
67+
$redacted = [regex]::Replace(
68+
$redacted,
69+
'(?i)(?:[A-Z]:\\|\\\\)[^\r\n`"]+(?:\\[^\r\n`"]+)*',
70+
'[redacted-path]'
71+
)
72+
73+
return $redacted
74+
}
75+
4076
$repoRoot = (Resolve-Path (Join-Path $PSScriptRoot "..")).Path
4177
$inputDir = Resolve-RepoPath $InputDir
4278
$outPath = Resolve-RepoPath $Out
@@ -61,7 +97,7 @@ if (-not $ThumbHeight -or $ThumbHeight -lt 1) {
6197
Add-Type -AssemblyName System.Drawing
6298

6399
$pngs = Get-ChildItem -Path $inputDir -Recurse -File -Filter "*.png" | Where-Object {
64-
$_.FullName -ne $outPath
100+
$_.FullName -ne $outPath -and $_.Name -notmatch '^(?i)(?:visual-proof-)?contact-sheet.*\.png$'
65101
} | Sort-Object FullName
66102
if ($pngs.Count -eq 0) {
67103
throw "No PNG images were found under $inputDir"
@@ -80,15 +116,17 @@ $summary = [ordered]@{
80116
Status = "Running"
81117
StartedUtc = [DateTimeOffset]::UtcNow.ToString("O")
82118
FinishedUtc = $null
83-
InputDir = $inputDir
84-
Output = $outPath
119+
InputDir = Get-DisplayPath $inputDir
120+
Output = Get-DisplayPath $outPath
85121
Columns = $Columns
86122
ThumbWidth = $ThumbWidth
87123
ThumbHeight = $ThumbHeight
88124
ImageCount = $pngs.Count
89125
Rows = $rows
90126
SheetWidth = $sheetWidth
91127
SheetHeight = $sheetHeight
128+
RedactionMode = if ($RedactText) { "pixel-masked-thumbnails+text" } else { "none" }
129+
PublishSafe = [bool]$RedactText
92130
Images = @()
93131
}
94132

@@ -114,7 +152,31 @@ try {
114152
$highlightPen = New-Object System.Drawing.Pen([System.Drawing.Color]::FromArgb(179, 179, 179))
115153
$cardBrush = New-Object System.Drawing.SolidBrush([System.Drawing.Color]::White)
116154
$labelBgBrush = New-Object System.Drawing.SolidBrush([System.Drawing.Color]::FromArgb(235, 237, 240))
117-
$resources += $titleBrush, $labelBrush, $borderPen, $highlightPen, $cardBrush, $labelBgBrush
155+
$maskBrush = New-Object System.Drawing.SolidBrush([System.Drawing.Color]::FromArgb(245, 246, 248))
156+
$resources += $titleBrush, $labelBrush, $borderPen, $highlightPen, $cardBrush, $labelBgBrush, $maskBrush
157+
158+
function Mask-ThumbnailTextZones {
159+
param(
160+
[System.Drawing.Graphics]$Graphics,
161+
[int]$X,
162+
[int]$Y,
163+
[int]$Width,
164+
[int]$Height,
165+
[System.Drawing.Brush]$Brush
166+
)
167+
168+
if ($Width -le 0 -or $Height -le 0) {
169+
return
170+
}
171+
172+
$topMaskHeight = [Math]::Min($Height, [Math]::Max(36, [int][Math]::Round($Height * 0.30)))
173+
$bottomMaskHeight = [Math]::Min([Math]::Max(20, [int][Math]::Round($Height * 0.16)), $Height)
174+
175+
$Graphics.FillRectangle($Brush, $X, $Y, $Width, $topMaskHeight)
176+
if ($bottomMaskHeight -lt $Height) {
177+
$Graphics.FillRectangle($Brush, $X, $Y + $Height - $bottomMaskHeight, $Width, $bottomMaskHeight)
178+
}
179+
}
118180

119181
$title = "XeCLI visual proof contact sheet"
120182
$graphics.DrawString($title, $titleFont, $titleBrush, 16, 10)
@@ -137,9 +199,10 @@ try {
137199
$graphics.DrawRectangle($highlightPen, $imageAreaX, $labelY, $imageAreaWidth, $labelHeight)
138200

139201
$label = Get-RelativeDisplayPath -BasePath $inputDir -Path $file.FullName
202+
$displayLabel = if ($RedactText) { Redact-Text $label } else { $label }
140203
$summary.Images += [ordered]@{
141-
File = $file.FullName
142-
Label = $label
204+
File = Get-DisplayPath $file.FullName
205+
Label = $displayLabel
143206
Size = $file.Length
144207
LastWriteTimeUtc = $file.LastWriteTimeUtc.ToString("O")
145208
}
@@ -154,6 +217,9 @@ try {
154217

155218
$graphics.FillRectangle([System.Drawing.Brushes]::White, $imageAreaX, $imageAreaY, $ThumbWidth, $ThumbHeight)
156219
$graphics.DrawImage($image, $drawX, $drawY, $drawWidth, $drawHeight)
220+
if ($RedactText) {
221+
Mask-ThumbnailTextZones -Graphics $graphics -X $imageAreaX -Y $imageAreaY -Width $ThumbWidth -Height $ThumbHeight -Brush $maskBrush
222+
}
157223
}
158224
finally {
159225
$image.Dispose()
@@ -163,7 +229,7 @@ try {
163229
$format = New-Object System.Drawing.StringFormat
164230
$format.Trimming = [System.Drawing.StringTrimming]::EllipsisCharacter
165231
$format.FormatFlags = [System.Drawing.StringFormatFlags]::LineLimit
166-
$graphics.DrawString($label, $labelFont, $labelBrush, $textRect, $format)
232+
$graphics.DrawString($displayLabel, $labelFont, $labelBrush, $textRect, $format)
167233
$format.Dispose()
168234
}
169235

@@ -177,6 +243,12 @@ catch {
177243
finally {
178244
$summary.FinishedUtc = [DateTimeOffset]::UtcNow.ToString("O")
179245
$summaryPath = [System.IO.Path]::ChangeExtension($outPath, ".json")
246+
if ($RedactText) {
247+
foreach ($imageSummary in $summary.Images) {
248+
$imageSummary.Label = Redact-Text $imageSummary.Label
249+
$imageSummary.File = Redact-Text $imageSummary.File
250+
}
251+
}
180252
$summary | ConvertTo-Json -Depth 8 | Set-Content -Path $summaryPath -Encoding UTF8
181253

182254
foreach ($font in $fonts) {
@@ -191,9 +263,11 @@ finally {
191263

192264
[pscustomobject]@{
193265
Status = $summary.Status
194-
Output = $outPath
195-
Summary = [System.IO.Path]::ChangeExtension($outPath, ".json")
266+
Output = Get-DisplayPath $outPath
267+
Summary = Get-DisplayPath ([System.IO.Path]::ChangeExtension($outPath, ".json"))
196268
ImageCount = $summary.ImageCount
197269
Rows = $summary.Rows
198270
Columns = $summary.Columns
271+
RedactionMode = $summary.RedactionMode
272+
PublishSafe = $summary.PublishSafe
199273
}

0 commit comments

Comments
 (0)