diff --git a/.claude/skills/run-socktuner/SKILL.md b/.claude/skills/run-socktuner/SKILL.md index be03eb1..b329739 100644 --- a/.claude/skills/run-socktuner/SKILL.md +++ b/.claude/skills/run-socktuner/SKILL.md @@ -1,6 +1,6 @@ --- name: run-socktuner -description: Build, launch, drive, screenshot and probe the SockTuner WPF desktop app on Windows. Use when asked to run, start, open, screenshot, inspect the UI of, or capture an inventory from SockTuner, or to verify a change in the real app rather than in tests. +description: Build, launch, drive and screenshot the SockTuner WPF desktop app on Windows. Use when asked to run, start, open, screenshot, inspect the UI of, or verify a change in the real app rather than in tests. --- # Run SockTuner @@ -33,7 +33,6 @@ powershell.exe -NoProfile -File .claude/skills/run-socktuner/driver.ps1 "` | Selects a tab by name (substring match) | | `shot [path]` | PNG of the window → `.claude/skills/run-socktuner/shots/` | -| `probe` | Read-only inventory dump to JSON on the Desktop | | `stop` | Kills the process | A full verified cycle: @@ -82,19 +81,12 @@ the saved position no longer lands on an attached monitor. `Tuning plan` used to be last; it now sits with the other surfaces that act. The reference links moved out of `Preferences` into `Tools & references`. -## Inventory without the GUI +## Compatibility reports -`probe` runs the app's own `--probe` mode: a read-only capture of the whole inventory, -redacted (`machineName` masked, no addresses), written as JSON to the Desktop. It changes -nothing on the machine. This is the fastest way to inspect what the app *sees* without -touching the UI: - -```bash -powershell.exe -NoProfile -File .claude/skills/run-socktuner/driver.ps1 probe -# OK probe -> C:\Users\\Desktop\socktuner-probe-20260828-022443.json (410.4 KB) -``` - -Committed probe corpora live in `alpha-tester-output/`. +Compatibility reports are intentionally created only through the visible UI flow under +**Preferences → Help improve SockTuner**. The user reviews the complete JSON before saving +and explicitly chooses whether to open the GitHub issue form. The agent driver does not +bypass that consent flow. ## Tests @@ -102,21 +94,19 @@ Committed probe corpora live in `alpha-tester-output/`. dotnet test SockTuner.sln ``` -659 pass, 12 skipped. The 12 skipped are read-only live-inventory checks against the real -adapters and the two device-level settings; they are safe on a normal desktop and mutate +The default suite reports its current pass/skip counts. Skipped tests are read-only +live-inventory checks against real adapters; they are safe on a normal desktop and mutate nothing: ```bash SOCKTUNER_LIVE_INVENTORY=1 dotnet test SockTuner.sln ``` -671 pass, 0 skipped. - ## Never run these on a real machine `--verify-tcp-writes` **writes to the live TCP stack** and `--verify-device-writes` **enables and disables a real adapter, writes PnPCapabilities and creates a QoS policy**. -Both are gated behind `SOCKTUNER_VM_WRITE_TEST=1` so a mistyped `--probe` cannot trigger +Both are gated behind `SOCKTUNER_VM_WRITE_TEST=1`, so an argument alone cannot trigger them, and both belong in a disposable VM only. The driver deliberately exposes no command for either. @@ -161,13 +151,6 @@ path is skipped — the run refuses to disable the adapter carrying the default - **Screenshot tooling downscales.** A desktop-capture MCP may return an image scaled from 3640x2144 to ~1833x1080, so coordinates read off that image are wrong by a ~1.99 factor. `driver.ps1 shot` captures the window rect at native size and sidesteps this. -- **`--probe` used to end on a modal.** It now attaches to the calling console, prints the - report path there and exits on its own; the message box is kept only for someone who - double-clicked the exe and has no console to read. The driver still waits for the file - before returning, which is what makes it reliable, but it no longer has to kill a process - left holding a dialog nobody could dismiss. -- **Probe takes longer than you expect.** A full inventory capture exceeded 6 s here, so a - fixed sleep is not enough; the driver polls for up to 120 s. - **`pwsh` 7 cannot load `UIAutomationClient`.** Use `powershell.exe`. - **A stale VM registration breaks every `-Name` Hyper-V cmdlet on this host.** `Get-VM`, `Checkpoint-VM -Name`, `Copy-VMFile -Name` and friends enumerate all VMs first, hit the @@ -176,10 +159,9 @@ path is skipped — the run refuses to disable the adapter carrying the default - **PowerShell Direct runs over VMBus, not the network.** That is what makes it safe to disable an adapter in the guest from the host: the session survives losing all guest networking. It does need guest credentials; there is no passwordless path. -- **A console-mode run has no console over PowerShell Direct.** `--probe` and the verify +- **A verification-mode run has no console over PowerShell Direct.** The verification modes attach to the caller's console when there is one and fall back to a message box when - there is not — and over PSDirect there is not, so the modal blocks forever. Start the - process detached and poll for the JSON, which is written before the message appears. + there is not. Start them detached in the disposable VM and poll for their JSON result. ## Troubleshooting @@ -188,6 +170,4 @@ path is skipped — the run refuses to disable the adapter carrying the default | `SockTuner window not found. Run "launch" first.` | The app is not running, or it was started as a shell child and already died. Re-run `launch`. | | `Not built. Run: driver.ps1 build` | The Release exe is missing. Run `build`. | | `No tab matching ''` | Run `tabs` for the exact names; matching is substring, case-insensitive. | -| `Probe produced no JSON on the Desktop within 120s.` | Check for a stuck `SockTuner probe` process: `Get-Process SockTuner`. Kill it and retry. | | `Could not raise the SockTuner window; another window is on top…` | Something is covering the app and Windows refused the foreground handover. Minimise it, or click the SockTuner window once, then re-run `shot`. | -| A leftover window titled `SockTuner probe` | An earlier probe attempt was interrupted. `powershell.exe -NoProfile -File .claude/skills/run-socktuner/driver.ps1 stop` clears all SockTuner processes. | diff --git a/.claude/skills/run-socktuner/driver.ps1 b/.claude/skills/run-socktuner/driver.ps1 index ece3f42..2d2f515 100644 --- a/.claude/skills/run-socktuner/driver.ps1 +++ b/.claude/skills/run-socktuner/driver.ps1 @@ -152,33 +152,6 @@ switch ($Command) { "OK shot ${w}x${ht} -> $path" } - # Read-only inventory dump to JSON. Ends on a modal this driver cannot click, so the - # process is stopped once the file lands. Nothing on the machine is changed. - 'probe' { - if (-not (Test-Path $Exe)) { throw "Not built. Run: driver.ps1 build" } - $before = Get-Date - $desktop = [Environment]::GetFolderPath('Desktop') - $proc = Start-Process -FilePath $Exe -ArgumentList '--probe' -WorkingDirectory (Split-Path $Exe) -PassThru - # The JSON is written BEFORE the modal appears, so wait for the file and then close - # that exact process. Do not try to click the dialog: it is a Win32 #32770 whose - # buttons this build does not expose to UI Automation, so a UIA click never lands - # and the process is left alive holding a modal on the user's desktop. - $json = $null - $deadline = (Get-Date).AddSeconds(120) - while ((Get-Date) -lt $deadline) { - Start-Sleep -Milliseconds 750 - $json = Get-ChildItem $desktop -Filter 'socktuner-probe-*.json' -ErrorAction SilentlyContinue | - Where-Object { $_.LastWriteTime -ge $before } | - Sort-Object LastWriteTime -Descending | Select-Object -First 1 - if ($json) { break } - if ($proc.HasExited) { break } - } - if (-not $json) { throw 'Probe produced no JSON on the Desktop within 120s.' } - Start-Sleep -Milliseconds 500 - if (-not $proc.HasExited) { Stop-Process -Id $proc.Id -Force -ErrorAction SilentlyContinue } - "OK probe -> $($json.FullName) ($([math]::Round($json.Length/1KB,1)) KB)" - } - 'stop' { Get-Process SockTuner -ErrorAction SilentlyContinue | Stop-Process -Force 'OK stopped' @@ -193,7 +166,6 @@ SockTuner driver — commands: tabs list navigation tabs, * marks the selected one select "" select a tab by name (substring match) shot [path] PNG of the window -> .claude/skills/run-socktuner/shots/ - probe --probe read-only inventory dump to JSON on the Desktop stop kill the process '@ } diff --git a/.github/ISSUE_TEMPLATE/compatibility-report.yml b/.github/ISSUE_TEMPLATE/compatibility-report.yml new file mode 100644 index 0000000..612fc13 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/compatibility-report.yml @@ -0,0 +1,25 @@ +name: Hardware compatibility report +description: Share a privacy-safe SockTuner capability report from real hardware. +title: "Compatibility: " +body: + - type: markdown + attributes: + value: | + Thank you for helping validate SockTuner on real hardware. + + In SockTuner, open **Preferences → Help improve SockTuner → Create compatibility report**. Review the plain-text JSON file, then drag it into the field below. The report excludes all current setting values, persistent device identifiers, network addresses, paths, machine name, and exact timestamps. + - type: textarea + id: report + attributes: + label: Compatibility report + description: Drag the generated SockTuner-compatibility.json file here. + placeholder: Drag and drop SockTuner-compatibility.json here. + validations: + required: true + - type: checkboxes + id: consent + attributes: + label: Consent + options: + - label: I reviewed the generated JSON and consent to publishing it in this GitHub issue. + required: true diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 165780f..1540dcf 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -36,6 +36,11 @@ jobs: - name: Verify formatting run: dotnet format SockTuner.sln --no-restore --verify-no-changes + - name: Verify capability archive + run: | + python -m unittest tools/test_build_probe_archive.py + python tools/build-probe-archive.py --check + - name: Build run: dotnet build SockTuner.sln -c Release --no-restore -p:ContinuousIntegrationBuild=true diff --git a/.gitignore b/.gitignore index 66aae27..248ca80 100644 --- a/.gitignore +++ b/.gitignore @@ -3,6 +3,8 @@ **/obj/ artifacts/ TestResults/ +__pycache__/ +*.py[cod] # IDE and user state .vs/ diff --git a/README.md b/README.md index 19cb86b..71ca1f2 100644 --- a/README.md +++ b/README.md @@ -18,46 +18,22 @@

> [!WARNING] -> **SockTuner is in active development (alpha) and is NOT ready for production use.** -> The project is at **Step 7b of 10: NIC and driver controls**. This build **can change live network settings**. Applying a NIC property restarts that adapter and briefly drops its link — never apply over a remote session on the adapter you are changing, and be able to recover the machine's network without remote access. Every change is snapshotted, verified by read-back, and reversible from the audit history, but treat it as alpha software. +> **SockTuner is a community diagnostic alpha, not production software.** Read-only inventory and diagnostics are the primary public surface. Tuning is experimental and can change live network settings. Applying a NIC property restarts that adapter and briefly drops its link — never do this through the connection being changed. Every write requires consent and elevation, is snapshotted, verified by read-back, audited, and reversible. SockTuner is intended for tweakers, technicians, competitive gamers, system integrators, and power users who need one place to inspect and control the Windows networking stack, network adapters, and NIC driver settings. It is not a generic “make my ping lower” button. SockTuner will show the current value, proposed value, scope, expected trade-off, restart requirement, and rollback data for every change. -## Help wanted: hardware capability probe +## Help improve hardware compatibility -SockTuner exposes only settings that the NIC driver actually advertises. Virtual machines do not expose real driver properties, so we are collecting capability reports from real hardware — especially **Intel I219/I225/I226** and **Realtek RTL8111/RTL8125** adapters. +SockTuner exposes only settings that the installed NIC driver actually advertises. We need reports from real hardware — especially **Intel I219/I225/I226**, **Realtek RTL8111/RTL8125**, Killer/Qualcomm, Broadcom, and Marvell adapters. -If you have one of these NICs, you can contribute in two minutes with the built-in read-only probe. **The probe changes nothing on your PC** — it only reads the same inventory the app already displays. +1. Download and extract the latest Windows x64 build from [Releases](https://github.com/PrimeBuild-pc/SockTuner/releases). +2. Refresh the inventory, then open **Preferences → Help improve SockTuner**. +3. Choose **Create compatibility report**, review the plain-text JSON, and let SockTuner open the dedicated GitHub issue form. +4. Attach the JSON file to the issue. -### How to run the probe - -1. Download the latest `SockTuner-*-win-x64.zip` from [Releases](https://github.com/PrimeBuild-pc/SockTuner/releases) and extract it. -2. The build is currently **unsigned**, so Windows SmartScreen will warn you: click **More info → Run anyway**. You can inspect the source and build it yourself with `dotnet publish` if you prefer. -3. Open a terminal in the extracted folder (File Explorer address bar → type `cmd` → Enter) and run: - ``` - SockTuner.exe --probe - ``` -4. A dialog confirms the report location: `socktuner-probe-.json` on your **Desktop**. - -### What the probe collects - -| Included (hardware identity) | Masked (personal data) | -| --- | --- | -| NIC description, driver provider/version/date, INF name | Machine name | -| PCI vendor/device ID, reported as the driver's component ID (`PCI\VEN_xxxx&DEV_xxxx`) | IP addresses, gateways, DNS servers, routes | -| NDIS advanced properties: keyword, current value, default, type, valid ranges/enums | MAC address (only the vendor OUI prefix is kept) | -| OS version, admin state, CPU count | User-assigned values (e.g. a custom `NetworkAddress` MAC) | - -The report is a plain-text JSON file — open it in any editor and check it yourself before sending. - -### How to send your report - -- **GitHub:** open an [issue](https://github.com/PrimeBuild-pc/SockTuner/issues/new) titled `Probe report: ` and attach the JSON file. -- **Discord:** open a ticket on our Discord server (invite link in the repository sidebar) and attach the JSON file. - -Include your Windows version if you know it. Thank you! +The report contains the adapter model, driver version, OS version, and driver-advertised keywords and constraints. It excludes all current setting values, persistent adapter/PNP identifiers, MAC and IP addresses, routes, DNS servers, INF and user paths, machine name, and exact timestamps. Creating it is read-only and changes nothing on the PC. ## Product goals @@ -104,16 +80,11 @@ The reference scripts in this private workspace are research inputs, not product ## Current stage -- Architecture and product scope approved. -- Step 1 is complete: the dark Metro shell, application icon, OS/adapter inventory, driver-advertised NDIS discovery, filtering/copy, and DPI validation pass. -- Native IPv4/IPv6 routes and metrics, interface indexes/MTU/DNS, network profiles and bindings, NIC counters, TCP templates, QoS policies, global/RSS/RSC/LSO/checksum/USO/URO offload state, Winsock catalog, bounded structured logs, full/redacted snapshot export, retention preferences, and log export provide the Step 2 inventory. -- Steps 1–2 now pass inventory, export, search/copy, dark-theme, and 100–200% WPF DPI validation. -- Step 3 adds explicit quick/standard/extended diagnostics, concurrent boundary probes, full statistics/timelines, route/MTU/counter evidence, and bounded continuous monitoring. -- Step 4 includes versioned JSON, self-contained offline HTML, bounded local history, redacted history export, identical-parameter before/after comparison, and multi-run trends. -- Step 5 is complete with an allowlisted dry-run cart, exact rollback preview, bounded audit history, deterministic transactions, failure injection, and a strict typed elevated-worker protocol. -- Step 6 is complete: the first two low-disruption MMCSS settings passed direct and published-worker apply/read/rollback/read gates on disposable Windows 10 22H2 and Windows 11 VMs. NIC/driver writes and the normal UI remain locked while Step 7 starts. -- Step 7a added a read-only `--probe` mode: it writes a redacted capability report (`socktuner-probe-.json` on the Desktop) that collaborators with real Intel/Realtek NICs can share. Personal data is masked; driver identity, NDIS keywords, defaults, and valid ranges/enums are preserved. The probe changes nothing on the machine. -- Step 7b unlocks live writes. The **Tuning plan** tab lists the properties the selected driver actually advertises, filtered by intent preset — latency, bandwidth, power and wake, Wi-Fi radio, VLAN and identity — with preview, apply, and exact rollback from the audit history. Capability reports so far cover Intel I226-V and Wireless-AC 3168, Realtek RTL8125, 8852CE and 8922AE, and MediaTek MT7925; the generated [capability archive index](alpha-tester-output/INDEX.md) is the authoritative list. +- Native read-only inventory covers adapters, routes, interfaces, DNS, profiles, bindings, NIC counters, TCP templates, QoS, offloads, interrupts, Winsock, driver identity, and driver-advertised properties. +- The complete network check measures each path boundary, latency/loss/jitter, DNS and TCP timing, path MTU, route quality, counter deltas, and game-specific playability; loaded-latency and throughput traffic remain separate opt-in tests. +- Versioned reports, bounded local history, redacted exports, before/after comparison, trends, monitoring, and imported capture reports are available. +- Experimental writes use one allowlisted tuning plan with dry run, consent, elevation, stale-state refusal, read-back verification, audit, visible recovery, and exact rollback. +- Real-hardware coverage is crowdsourced through the in-app compatibility report. The generated [capability archive index](alpha-tester-output/INDEX.md) lists current Intel, Realtek, and MediaTek coverage. ## How a change is applied @@ -127,4 +98,4 @@ The reference scripts in this private workspace are research inputs, not product Changing network, registry, adapter, or driver settings can interrupt connectivity or reduce stability and throughput. Applying a NIC property restarts that adapter, which briefly drops the link — do not apply over a remote session on the adapter being changed. Test on a machine you can recover without remote access. SockTuner never invents a value or a range: it exposes only what the installed driver advertises, and treats any keyword it has not characterised as high risk. -SockTuner is released under the [MIT License](LICENSE). The public contribution policy is still being defined; probe reports via issues or Discord are the best way to help right now. +SockTuner is released under the [MIT License](LICENSE). Compatibility reports and bug reports are welcome through the dedicated GitHub issue forms. diff --git a/SECURITY.md b/SECURITY.md index 24f6c6c..3ee9eae 100644 --- a/SECURITY.md +++ b/SECURITY.md @@ -32,7 +32,7 @@ The privilege boundary is the interesting part, and it is the part worth attacki or driver advertises. - Anything that turns imported, untrusted data — a capture report, an exported diagnostic, a probe report — into code execution, a file path, or a write. -- Anything that causes an exported report or a probe report to contain data the redaction claims to +- Anything that causes an exported report or compatibility report to contain data the redaction claims to have removed. - Anything that leaves the machine unable to reach the network with no path back to the captured state. diff --git a/alpha-tester-output/INDEX.md b/alpha-tester-output/INDEX.md index 586a625..458bf3e 100644 --- a/alpha-tester-output/INDEX.md +++ b/alpha-tester-output/INDEX.md @@ -1,6 +1,6 @@ # Capability archive -Redacted `--probe` reports, split one file per adapter model. This is the reference for +Privacy-safe compatibility reports, split one file per adapter model. This is the reference for which hardware SockTuner has real capability data for, and therefore which keywords its catalog is characterised against. Regenerate with `python tools/build-probe-archive.py`. @@ -9,8 +9,8 @@ collapses to a single entry; the richer record wins when a model appears in seve Raw reports are kept under `reports/` for provenance. `capabilities` carries the structured driver constraints (valid values, min/max/step, -default) that the tuning surface uses. Reports captured before schema 12 have only -`ndisProperties`; re-running the probe on that hardware upgrades the entry. +default) that the tuning surface uses. Older probe reports may have only +`ndisProperties`; creating a new compatibility report on that hardware upgrades the entry. ## Physical adapters @@ -52,10 +52,10 @@ Hardware with no report yet, roughly in order of how common it is among the targ ### Adding a report -1. Run `SockTuner.exe --probe` on the machine; it writes a redacted report to the Desktop. -2. Drop the file into this folder, or pass its folder to the build script. +1. In SockTuner, open Preferences → Help improve SockTuner → Create compatibility report. +2. Review the JSON, then drop it into this folder or pass its folder to the build script. 3. Run `python tools/build-probe-archive.py` to file it, split it per model and refresh this index. 4. Run `python tools/build-probe-archive.py --check` to verify regeneration produces no diff. -Reports contain no machine name, IP addresses, routes or full MAC addresses; the vendor OUI -prefix and driver identity are kept deliberately, since they are the point of the archive. +Current reports contain no persistent device identifiers, network addresses, user paths, +machine name or exact timestamps. Hardware model and driver identity are kept deliberately. diff --git a/docs/JACKPOTS_ZENIT_NDIS_CANDIDATES.md b/docs/JACKPOTS_ZENIT_NDIS_CANDIDATES.md index 9dd59ba..69214eb 100644 --- a/docs/JACKPOTS_ZENIT_NDIS_CANDIDATES.md +++ b/docs/JACKPOTS_ZENIT_NDIS_CANDIDATES.md @@ -20,7 +20,7 @@ > > The ~90 properties below are the *superset the Zenit tool writes blindly by > name*. They are kept here only as a -> **watch-list**: if a future probe report shows one on real hardware, promote it into the +> **watch-list**: if a future compatibility report shows one on real hardware, promote it into the > corpus with a real range/enum; until then it is a name to recognise, never a value to apply. > **The Zenit "forced value" columns are the tool's opinion, unverified — do not import them.** @@ -42,7 +42,7 @@ SockTuner's existing risk model: ## A. Standardized (`*`) keywords — legitimate candidates when the driver advertises them -Cross-check each against `NicKeywordCatalog`; add the ones a probe report confirms. +Cross-check each against `NicKeywordCatalog`; add the ones a compatibility report confirms. ### Offloads (checksum / LSO / USO / RSC / IPsec / encap) | Keyword | Zenit value | Note | diff --git a/docs/ROADMAP.md b/docs/ROADMAP.md index cbbf63e..916355a 100644 --- a/docs/ROADMAP.md +++ b/docs/ROADMAP.md @@ -149,7 +149,7 @@ Exit criteria: Step 7 is split into two gates: -- **7a — capability collection (no disposable hardware required):** the read-only `--probe` mode captures a redacted inventory from collaborator PCs with real Intel/Realtek NICs. Personal data (machine name, IPs, MAC device octets, user-assigned values) is masked; hardware identity (driver, PNP ID, NDIS keywords, defaults, ranges/enums) is preserved. Probe reports seed the capability matrix and fake-platform fixtures. +- **7a — capability collection (no disposable hardware required):** the in-app compatibility-report flow captures a privacy-safe inventory from collaborator PCs with real NICs and opens a dedicated GitHub issue form. All current setting values, persistent adapter/PNP identifiers, addresses, paths, machine name, and exact timestamps are omitted; adapter model, driver version, NDIS keywords, defaults, ranges and enums seed the capability matrix and fake-platform fixtures. - **7b — write unlock (alpha):** NIC/driver writes are enabled behind versioned in-app consent, UAC elevation, driver-advertised validation re-read inside the elevated worker, and a typed confirmation for high-risk or experimental changes. The static per-setting allowlist is retained for registry-backed catalog entries only; for NIC properties the driver's own advertised constraints are the allowlist, so an unsupported keyword or value cannot be planned or written. Capability coverage is currently Intel I226-V and Wireless-AC 3168, Realtek RTL8125 and 8852CE, and MediaTek MT7925 — keywords outside that corpus are exposed but reported as high risk and uncharacterised. Deliverables: @@ -220,7 +220,7 @@ Exit criteria: The queue defines completion gates. A read-only prerequisite from the next item may land in the same reviewed increment, but no step is marked complete and no writable scope unlocks until every earlier exit criterion passes. -1. **P1 / Step 7b:** broaden real-hardware validation of capability-advertised NIC and driver controls, and grow the characterised-keyword corpus as more probe reports arrive. +1. **P1 / Step 7b:** broaden real-hardware validation of capability-advertised NIC and driver controls, and grow the characterised-keyword corpus as more compatibility reports arrive. 2. **P2 / Step 10:** the gates that need what this project does not yet have — a code-signing certificate, and real machines across the Windows and locale matrix. Listed below rather than left implicit, because none of them can be closed by writing code. Steps 8 and 9 are complete. Step 8 closed with three things rather than a large surface. The interface metric joined MTU as a per-interface override whose restore is the *removal* of the value, since absent means Windows derives the metric from link speed — writing a number back would be a different setting that happened to match, not a rollback. A remote-session guard now stands in front of every change that drops the link: it does not work out which adapter carries the session, so it assumes this one might and forces the typed confirmation, because being wrong in that direction costs a sentence and being wrong in the other direction costs the machine. An unrecognised restart requirement is treated as disruptive, and a test fails if one appears that nobody classified. diff --git a/src/SockTuner/App.xaml.cs b/src/SockTuner/App.xaml.cs index e2a06bd..7f2b94f 100644 --- a/src/SockTuner/App.xaml.cs +++ b/src/SockTuner/App.xaml.cs @@ -18,12 +18,6 @@ protected override void OnStartup(StartupEventArgs e) return; } - if (e.Args.Length == 1 && string.Equals(e.Args[0], "--probe", StringComparison.Ordinal)) - { - Shutdown(RunProbe()); - return; - } - if (e.Args.Length == 1 && string.Equals(e.Args[0], VerifyTcpWritesArgument, StringComparison.Ordinal)) { Shutdown(RunTcpWriteVerification()); @@ -55,8 +49,7 @@ protected override void OnStartup(StartupEventArgs e) /// /// Set to 1 in the guest to arm the write verification. The argument alone is not enough: this - /// mode writes to the live TCP stack, so it must be impossible to trigger by mistyping --probe - /// on a real desktop. + /// mode writes to the live TCP stack, so an argument alone must not arm it on a real desktop. /// internal const string VerifyTcpWritesGate = "SOCKTUNER_VM_WRITE_TEST"; @@ -171,42 +164,13 @@ private static int RunDeviceWriteVerification() } } - // Read-only hardware capability probe for collaborators: captures the inventory, - // redacts personal data, and writes a shareable JSON report. Mutates nothing. - private static int RunProbe() - { - try - { - var snapshot = new SystemInventoryService().Capture(); - var path = Path.Combine( - Environment.GetFolderPath(Environment.SpecialFolder.Desktop), - $"socktuner-probe-{DateTime.Now:yyyyMMdd-HHmmss}.json"); - File.WriteAllText(path, SnapshotExporter.Serialize(snapshot, probe: true)); - Report( - "SockTuner probe", - $"Probe report saved to:{Environment.NewLine}{path}{Environment.NewLine}{Environment.NewLine}" - + "Nothing on this PC was changed. Share this file with the SockTuner team.", - MessageBoxImage.Information); - return 0; - } - catch (Exception exception) - { - Report("SockTuner probe", $"Probe failed: {exception.Message}", MessageBoxImage.Error); - return 1; - } - } - /// - /// Reports the outcome of a console-invoked mode. The README tells a contributor to run the - /// probe from a terminal, so the terminal is where the answer belongs: this writes there when - /// there is one to write to. The message box is kept for the person who double-clicked the exe - /// and has nowhere else to read it — that case has no console to attach to, which is exactly - /// the condition tested here. + /// Reports the outcome of a console-invoked verification mode. This writes to the parent + /// terminal when one exists; otherwise a message box is the only visible channel. /// /// /// A WPF process is built without a console, so it has to borrow the parent's. When it cannot, - /// nothing has been written and the modal is the only remaining channel. This is also what - /// stopped an automated probe run from leaving a modal nobody could dismiss. + /// nothing has been written and the modal is the only remaining channel. /// private static void Report(string title, string message, MessageBoxImage severity) { diff --git a/src/SockTuner/Assets/i18n/translations.json b/src/SockTuner/Assets/i18n/translations.json index 73a5cb8..22bbf7b 100644 --- a/src/SockTuner/Assets/i18n/translations.json +++ b/src/SockTuner/Assets/i18n/translations.json @@ -3173,5 +3173,170 @@ "es": "{0}{1}{2}{3}Enlace {4}, direcciones {5}, puertas de enlace {6}.", "ru": "{0}{1}{2}{3}Канал {4}, адреса {5}, шлюзы {6}.", "zh-Hans": "{0}{1}{2}{3}链路 {4},地址 {5},网关 {6}。" + }, + "Create compatibility report…": { + "es": "Crear informe de compatibilidad…", + "ru": "Создать отчёт о совместимости…", + "zh-Hans": "创建兼容性报告…" + }, + "Create compatibility report": { + "es": "Crear informe de compatibilidad", + "ru": "Создать отчёт о совместимости", + "zh-Hans": "创建兼容性报告" + }, + "Help improve SockTuner": { + "es": "Ayuda a mejorar SockTuner", + "ru": "Помогите улучшить SockTuner", + "zh-Hans": "帮助改进 SockTuner" + }, + "Create a privacy-safe hardware capability report. It includes adapter model, driver version and supported settings; it excludes device IDs, addresses, paths, machine name and exact timestamps.": { + "es": "Crea un informe de capacidades de hardware que protege la privacidad. Incluye el modelo del adaptador, la versión del controlador y los ajustes compatibles; excluye identificadores de dispositivo, direcciones, rutas, el nombre del equipo y marcas de tiempo exactas.", + "ru": "Создайте безопасный для конфиденциальности отчёт о возможностях оборудования. Он включает модель адаптера, версию драйвера и поддерживаемые параметры, но исключает идентификаторы устройств, адреса, пути, имя компьютера и точные метки времени.", + "zh-Hans": "创建保护隐私的硬件功能报告。报告包含适配器型号、驱动程序版本和支持的设置;不包含设备 ID、地址、路径、计算机名称和精确时间戳。" + }, + "Refresh inventory before creating a compatibility report.": { + "es": "Actualiza el inventario antes de crear un informe de compatibilidad.", + "ru": "Обновите инвентаризацию перед созданием отчёта о совместимости.", + "zh-Hans": "请先刷新清单,再创建兼容性报告。" + }, + "The report includes adapter model, driver version and supported settings. It excludes persistent device IDs, addresses, paths, machine name and exact timestamps. Save it for review?": { + "es": "El informe incluye el modelo del adaptador, la versión del controlador y los ajustes compatibles. Excluye identificadores persistentes de dispositivo, direcciones, rutas, el nombre del equipo y marcas de tiempo exactas. ¿Guardarlo para revisarlo?", + "ru": "Отчёт включает модель адаптера, версию драйвера и поддерживаемые параметры. Он исключает постоянные идентификаторы устройств, адреса, пути, имя компьютера и точные метки времени. Сохранить его для проверки?", + "zh-Hans": "报告包含适配器型号、驱动程序版本和支持的设置,不包含持久设备 ID、地址、路径、计算机名称和精确时间戳。是否保存以供检查?" + }, + "SockTuner compatibility report (*.json)|*.json": { + "es": "Informe de compatibilidad de SockTuner (*.json)|*.json", + "ru": "Отчёт о совместимости SockTuner (*.json)|*.json", + "zh-Hans": "SockTuner 兼容性报告 (*.json)|*.json" + }, + "Compatibility report saved to {0}.": { + "es": "Informe de compatibilidad guardado en {0}.", + "ru": "Отчёт о совместимости сохранён в {0}.", + "zh-Hans": "兼容性报告已保存到 {0}。" + }, + "Compatibility report saved.": { + "es": "Informe de compatibilidad guardado.", + "ru": "Отчёт о совместимости сохранён.", + "zh-Hans": "兼容性报告已保存。" + }, + "The JSON file is plain text. Inspect it if you wish, then attach it to the GitHub issue. Open the issue form now?": { + "es": "El archivo JSON es texto sin formato. Revísalo si quieres y adjúntalo a la incidencia de GitHub. ¿Abrir ahora el formulario?", + "ru": "Файл JSON является обычным текстом. При желании проверьте его и прикрепите к задаче GitHub. Открыть форму задачи сейчас?", + "zh-Hans": "JSON 文件是纯文本。你可以先检查内容,然后将其附加到 GitHub 议题。现在打开议题表单吗?" + }, + "Compatibility report saved": { + "es": "Informe de compatibilidad guardado", + "ru": "Отчёт о совместимости сохранён", + "zh-Hans": "兼容性报告已保存" + }, + "GitHub issue form opened. Attach the saved JSON file before submitting.": { + "es": "Se abrió el formulario de incidencias de GitHub. Adjunta el archivo JSON guardado antes de enviarlo.", + "ru": "Форма задачи GitHub открыта. Перед отправкой прикрепите сохранённый файл JSON.", + "zh-Hans": "GitHub 议题表单已打开。提交前请附加已保存的 JSON 文件。" + }, + "Compatibility report failed: {0}": { + "es": "Error al crear el informe de compatibilidad: {0}", + "ru": "Не удалось создать отчёт о совместимости: {0}", + "zh-Hans": "兼容性报告失败:{0}" + }, + "Running application": { + "es": "Aplicación en ejecución", + "ru": "Запущенное приложение", + "zh-Hans": "正在运行的应用程序" + }, + "Choose a running application": { + "es": "Elegir una aplicación en ejecución", + "ru": "Выбрать запущенное приложение", + "zh-Hans": "选择正在运行的应用程序" + }, + "Recovery": { + "es": "Recuperación", + "ru": "Восстановление", + "zh-Hans": "恢复" + }, + "No successful change is waiting to be undone.": { + "es": "No hay ningún cambio correcto pendiente de deshacer.", + "ru": "Нет успешных изменений, ожидающих отмены.", + "zh-Hans": "没有等待撤销的成功更改。" + }, + "Undo last successful change": { + "es": "Deshacer el último cambio correcto", + "ru": "Отменить последнее успешное изменение", + "zh-Hans": "撤销上次成功更改" + }, + "Open recovery history": { + "es": "Abrir historial de recuperación", + "ru": "Открыть журнал восстановления", + "zh-Hans": "打开恢复历史记录" + }, + "Last reversible change: {0:g} · {1} setting(s).": { + "es": "Último cambio reversible: {0:g} · {1} ajuste(s).", + "ru": "Последнее обратимое изменение: {0:g} · параметров: {1}.", + "zh-Hans": "上次可撤销更改:{0:g} · {1} 个设置。" + }, + "Undo the successful change from {0:g} ({1} setting(s))?": { + "es": "¿Deshacer el cambio correcto de {0:g} ({1} ajuste(s))?", + "ru": "Отменить успешное изменение от {0:g} (параметров: {1})?", + "zh-Hans": "撤销 {0:g} 的成功更改({1} 个设置)?" + }, + "Run complete check": { + "es": "Ejecutar comprobación completa", + "ru": "Запустить полную проверку", + "zh-Hans": "运行完整检查" + }, + "Runs the read-only inventory and path checks together. Loaded-latency and throughput tests stay separate because they generate traffic.": { + "es": "Ejecuta conjuntamente el inventario y las comprobaciones de ruta de solo lectura. Las pruebas de latencia con carga y rendimiento permanecen separadas porque generan tráfico.", + "ru": "Вместе запускает инвентаризацию и проверку пути только для чтения. Тесты задержки под нагрузкой и пропускной способности остаются отдельными, поскольку создают трафик.", + "zh-Hans": "同时运行只读清单和路径检查。负载延迟与吞吐量测试会产生流量,因此保持独立。" + }, + "Review compatibility report": { + "es": "Revisar informe de compatibilidad", + "ru": "Проверка отчёта о совместимости", + "zh-Hans": "检查兼容性报告" + }, + "Review the complete JSON before saving": { + "es": "Revisa el JSON completo antes de guardarlo", + "ru": "Проверьте полный JSON перед сохранением", + "zh-Hans": "保存前检查完整 JSON" + }, + "Only attach this file if you are comfortable publishing the contents in a GitHub issue.": { + "es": "Adjunta este archivo solo si aceptas publicar su contenido en una incidencia de GitHub.", + "ru": "Прикрепляйте этот файл, только если согласны опубликовать его содержимое в задаче GitHub.", + "zh-Hans": "仅当你愿意在 GitHub 议题中公开其内容时,才附加此文件。" + }, + "Save report": { + "es": "Guardar informe", + "ru": "Сохранить отчёт", + "zh-Hans": "保存报告" + }, + "Report saved, but the GitHub issue form could not be opened: {0}": { + "es": "El informe se guardó, pero no se pudo abrir el formulario de incidencias de GitHub: {0}", + "ru": "Отчёт сохранён, но форму задачи GitHub открыть не удалось: {0}", + "zh-Hans": "报告已保存,但无法打开 GitHub 议题表单:{0}" + }, + "Create a privacy-safe hardware capability report. It includes adapter model, driver version and supported setting constraints; it excludes current values, device IDs, addresses, paths, machine name and exact timestamps.": { + "es": "Crea un informe de capacidades de hardware que protege la privacidad. Incluye el modelo del adaptador, la versión del controlador y las restricciones admitidas; excluye valores actuales, identificadores de dispositivo, direcciones, rutas, el nombre del equipo y marcas de tiempo exactas.", + "ru": "Создайте безопасный для конфиденциальности отчёт о возможностях оборудования. Он включает модель адаптера, версию драйвера и ограничения поддерживаемых параметров, но исключает текущие значения, идентификаторы устройств, адреса, пути, имя компьютера и точные метки времени.", + "zh-Hans": "创建保护隐私的硬件功能报告。报告包含适配器型号、驱动程序版本和支持的设置约束;不包含当前值、设备 ID、地址、路径、计算机名称和精确时间戳。" + }, + "The report includes adapter model, driver version and supported setting constraints. It excludes all current values, persistent device IDs, addresses, paths, machine name and exact timestamps. Save it for review?": { + "es": "El informe incluye el modelo del adaptador, la versión del controlador y las restricciones admitidas. Excluye todos los valores actuales, identificadores persistentes de dispositivo, direcciones, rutas, el nombre del equipo y marcas de tiempo exactas. ¿Guardarlo para revisarlo?", + "ru": "Отчёт включает модель адаптера, версию драйвера и ограничения поддерживаемых параметров. Он исключает все текущие значения, постоянные идентификаторы устройств, адреса, пути, имя компьютера и точные метки времени. Сохранить его для проверки?", + "zh-Hans": "报告包含适配器型号、驱动程序版本和支持的设置约束,不包含任何当前值、持久设备 ID、地址、路径、计算机名称和精确时间戳。是否保存以供检查?" + }, + "Undo the successful change from {0:g} ({1} setting(s))? Settings: {2}. Recovery can restart affected adapters and briefly interrupt connectivity.": { + "es": "¿Deshacer el cambio correcto de {0:g} ({1} ajuste(s))? Ajustes: {2}. La recuperación puede reiniciar los adaptadores afectados e interrumpir brevemente la conectividad.", + "ru": "Отменить успешное изменение от {0:g} (параметров: {1})? Параметры: {2}. Восстановление может перезапустить затронутые адаптеры и кратковременно прервать подключение.", + "zh-Hans": "撤销 {0:g} 的成功更改({1} 个设置)?设置:{2}。恢复可能会重启受影响的适配器并短暂中断连接。" + }, + "Running applications could not be listed: {0}": { + "es": "No se pudieron enumerar las aplicaciones en ejecución: {0}", + "ru": "Не удалось получить список запущенных приложений: {0}", + "zh-Hans": "无法列出正在运行的应用程序:{0}" + }, + "Confirm rollback": { + "es": "Confirmar reversión", + "ru": "Подтвердить откат", + "zh-Hans": "确认回滚" } } diff --git a/src/SockTuner/MainWindow.xaml b/src/SockTuner/MainWindow.xaml index 19be013..ed7783c 100644 --- a/src/SockTuner/MainWindow.xaml +++ b/src/SockTuner/MainWindow.xaml @@ -39,6 +39,7 @@ + @@ -161,6 +162,16 @@ + + + + +