diff --git a/CHANGELOG.md b/CHANGELOG.md
index 848003bc..6dd7e1e7 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -10,6 +10,18 @@ That paragraph is not decoration: the release workflow copies each entry verbati
the GitHub release body and the announcement discussion, so it is the first thing a
prospective user reads. CI fails a pull request whose newest entry is missing it.
+## [1.76.14] - 2026-09-04
+
+Double-clicking a cell in the App Updates or Windows Update list used to put a cursor in it, as if you could
+change what it said. You could type — and the app threw the change away. Those lists are reports now, and
+behave like it.
+
+### Fixed
+- **Report cells no longer pretend to be editable.** Ten cells across App Updates and Windows Update accepted
+ typing that went nowhere. One of them was the app's internal Id for a package, which is what gets handed to
+ Windows' installer — retyping it turned a row that would have updated into a row that reports an error, for
+ no reason the user could see. The tick boxes for choosing rows are untouched and still work.
+
## [1.76.13] - 2026-09-04
Five of the slowest screens never showed the thin progress line under their name in the left-hand list, so if
diff --git a/SysManager/SysManager.Tests/ArchitectureTests.cs b/SysManager/SysManager.Tests/ArchitectureTests.cs
index 2e69b976..bc014ed7 100644
--- a/SysManager/SysManager.Tests/ArchitectureTests.cs
+++ b/SysManager/SysManager.Tests/ArchitectureTests.cs
@@ -5496,6 +5496,90 @@ public void TheTimerResolutionQuery_BindsItsOutParametersCoarsestFinestCurrent()
private static partial Regex TimerQueryCall();
+ ///
+ /// A text column in a report grid must not accept typing.
+ ///
+ ///
+ /// Ten cells across App Updates and Windows Update entered edit mode on a double-click. Typing there
+ /// changed the in-memory row and nothing else, so the app appeared to accept an edit it silently discarded
+ /// — and one of them was App Updates' Id, the value WingetService.UpgradeAsync builds
+ /// winget upgrade --id "…" from, which turns a working row into an error row.
+ /// Per-column, not grid-level. Both grids carry a DataGridCheckBoxColumn for row selection,
+ /// and DataGrid.IsReadOnly="True" renders those checkboxes untickable — it would break "Upgrade
+ /// selected" outright. The 20 views that DO set it grid-wide have no checkbox column, which is why they
+ /// can. Reading the omission as forgetfulness and setting it globally would have been the wrong fix.
+ /// Nothing reaches a command line through an edited cell: WingetId.IsValid rejects the value
+ /// and AppUpdatesViewModel catches the ArgumentException per row. This is a UI-honesty rule,
+ /// not a security one.
+ ///
+ [Fact]
+ public void EveryReportTextColumn_IsReadOnly()
+ {
+ // view -> the column Header allowed to be editable, and why.
+ var editors = new Dictionary(StringComparer.Ordinal)
+ {
+ ["EnvironmentVariablesView.xaml"] =
+ "Value — this tab is an editor, not a report: Apply / Discard / Restore backup sit beside the "
+ + "grid and UpdateSourceTrigger=PropertyChanged carries each keystroke to the view-model",
+ };
+
+ var viewsDir = Path.Combine(FindAppProjectDir(), "Views");
+ var columnsChecked = 0;
+ var typeable = new List();
+
+ foreach (var file in Directory.GetFiles(viewsDir, "*.xaml"))
+ {
+ var name = Path.GetFileName(file);
+ var text = File.ReadAllText(file);
+
+ // Every grid in the file must be read-only for the grid-level form to count for any column in it.
+ var grids = DataGridOpeningTag().Matches(text).Select(m => m.Value).ToList();
+ if (grids.Count == 0) continue;
+ var gridReadOnly = grids.TrueForAll(g => g.Contains("IsReadOnly=\"True\"", StringComparison.Ordinal));
+
+ foreach (var column in ReportTextColumn().Matches(text).Select(m => m.Value))
+ {
+ columnsChecked++;
+ if (gridReadOnly || column.Contains("IsReadOnly", StringComparison.Ordinal)) continue;
+
+ var header = ColumnHeader().Match(column).Groups["header"].Value;
+ if (editors.TryGetValue(name, out var allowed)
+ && allowed.StartsWith(header + " ", StringComparison.Ordinal)) continue;
+
+ typeable.Add($"{name}: {header}");
+ }
+ }
+
+ // Vacuity floor: 125 text columns across the views today, measured with this exact pattern. The
+ // count matters twice over — a first pass at this used a pattern that also matched
+ // , a property element rather than a column. There are 43 of those, so
+ // the population read as 168 and every per-view "typeable cells" number was inflated with it.
+ Assert.True(columnsChecked >= 118,
+ $"only {columnsChecked} report text columns were parsed out of 125 measured — the pattern no "
+ + "longer matches the column shape, so this guard proves nothing.");
+
+ Assert.True(typeable.Count == 0,
+ "these report cells enter edit mode on a double-click, and the edit goes nowhere. Add "
+ + "IsReadOnly=\"True\" to the column — NOT to the DataGrid, which would also stop the user "
+ + "ticking a DataGridCheckBoxColumn. If the cell is genuinely meant to be edited, name it in the "
+ + "exception list in this test WITH its reason:\n " + string.Join("\n ", typeable));
+ }
+
+ /// A DataGrid opening tag.
+ [GeneratedRegex(@"]*?>", RegexOptions.Singleline)]
+ private static partial Regex DataGridOpeningTag();
+
+ ///
+ /// A DataGridTextColumn element. The negative lookahead keeps
+ /// <DataGridTextColumn.CellStyle> — a property element, not a column — out of the match.
+ ///
+ [GeneratedRegex(@"]*?/?>", RegexOptions.Singleline)]
+ private static partial Regex ReportTextColumn();
+
+ /// A column's Header attribute value.
+ [GeneratedRegex(@"Header=""(?[^""]*)""")]
+ private static partial Regex ColumnHeader();
+
///
/// A view-model that tracks its own "running" state must forward it to IsBusy.
///
diff --git a/SysManager/SysManager/SysManager.csproj b/SysManager/SysManager/SysManager.csproj
index 8ae75ce3..2b605436 100644
--- a/SysManager/SysManager/SysManager.csproj
+++ b/SysManager/SysManager/SysManager.csproj
@@ -10,9 +10,9 @@
SysManager
true
NU1603;NU1701
- 1.76.13
- 1.76.13.0
- 1.76.13.0
+ 1.76.14
+ 1.76.14.0
+ 1.76.14.0
SysManager
SysManager — Windows system monitoring toolkit by laurentiu021. Network, updates, health, logs, safe deep cleanup.
https://github.com/laurentiu021/SystemManager
diff --git a/SysManager/SysManager/Views/AppUpdatesView.xaml b/SysManager/SysManager/Views/AppUpdatesView.xaml
index d3b08a65..bd74cb04 100644
--- a/SysManager/SysManager/Views/AppUpdatesView.xaml
+++ b/SysManager/SysManager/Views/AppUpdatesView.xaml
@@ -88,12 +88,12 @@
-
-
-
-
-
-
+
+
+
+
+
+
diff --git a/SysManager/SysManager/Views/EnvironmentVariablesView.xaml b/SysManager/SysManager/Views/EnvironmentVariablesView.xaml
index 9a163918..71ad1d8b 100644
--- a/SysManager/SysManager/Views/EnvironmentVariablesView.xaml
+++ b/SysManager/SysManager/Views/EnvironmentVariablesView.xaml
@@ -131,6 +131,11 @@
+