@@ -4,9 +4,10 @@ applyTo: "**/*.cs,**/tests/**,**/*Tests/**"
44
55# Lessons Learned — RegiLattice Development
66
7- > Accumulated hard-won insights from the Python → C# migration and iterative test coverage sprints.
7+ > Accumulated hard-won insights from the Python → C# migration, test coverage sprints,
8+ > and the 453-tweak restoration campaign.
89> These rules are ** as important as the coding standards** — they prevent recurring mistakes.
9- > Last updated: 2025-07-20 (v3.0.0 , C# 13 / .NET 10.0-windows)
10+ > Last updated: 2025-07-21 (v3.1.5 , C# 13 / .NET 10.0-windows, 1 882 tweaks, 72 categories )
1011
1112---
1213
@@ -42,7 +43,7 @@ WinForms controls require a message pump and are fragile in xUnit. Focus tests o
4243## Unique TweakDef IDs — Global Uniqueness Required
4344
4445` TweakEngine.Register() ` throws ` ArgumentException ` on duplicate IDs.
45- Every tweak ID across ALL 71 modules must be globally unique.
46+ Every tweak ID across ALL 72 modules must be globally unique.
4647
4748``` csharp
4849// ❌ BAD — duplicate ID across modules will throw at registration
@@ -209,6 +210,109 @@ All references to the GitHub account must use `RajwanYair`:
209210
210211## Version & Metadata
211212
212- - Version lives in ` .csproj ` files — ` <Version>3.0.0 </Version> `
213+ - Version lives in ` .csproj ` files — ` <Version>3.1.5 </Version> `
213214- Do not duplicate version strings — single source of truth per project
214215- GitHub URLs: ` https://github.com/RajwanYair/RegiLattice `
216+
217+ ---
218+
219+ ## String Escape Sequences — Always Use Verbatim ` @"" `
220+
221+ Registry paths and file paths must use verbatim strings to avoid escape sequence errors:
222+
223+ ``` csharp
224+ // ✅ GOOD — verbatim string, no escape issues
225+ RegOp .SetDword (@" HKEY_LOCAL_MACHINE\SOFTWARE\Policies\Microsoft\Windows Defender" , " DisableAntiSpyware" , 1 )
226+
227+ // ❌ BAD — \S, \P, \W are invalid escape sequences → CS1009
228+ RegOp .SetDword (" HKEY_LOCAL_MACHINE\S OFTWARE\P olicies\M icrosoft\W indows Defender" , " DisableAntiSpyware" , 1 )
229+ ```
230+
231+ ** Common trap** : When batch-editing tweak files, forgetting the ` @ ` prefix on registry path strings.
232+ The C# compiler treats ` \S ` , ` \P ` , ` \W ` , ` \D ` , ` \M ` etc. as invalid escape sequences.
233+
234+ ---
235+
236+ ## Duplicate ID Detection — Check Before Adding
237+
238+ When adding tweaks in bulk across multiple modules, duplicates can sneak in:
239+
240+ ``` csharp
241+ // chrome.cs already has chrome-disable-translate
242+ // firefox.cs accidentally also defines chrome-disable-translate → CRASH at RegisterBuiltins()
243+ ```
244+
245+ ** Prevention** : Before adding a tweak ID, search the Tweaks/ directory:
246+
247+ ``` powershell
248+ Select-String -Pattern '"new-tweak-id"' -Path src/RegiLattice.Core/Tweaks/*.cs
249+ ```
250+
251+ During the 453-tweak restoration, 5 duplicate IDs were found across Chrome.cs and Firefox.cs.
252+
253+ ---
254+
255+ ## Tuple Deconstruction — Match Return Types Exactly
256+
257+ When calling helper methods, verify the return tuple arity:
258+
259+ ``` csharp
260+ // ShellRunner.RunPowerShell returns (int exitCode, string stdout, string stderr)
261+
262+ // ✅ GOOD — deconstruct all 3 values
263+ var (exitCode , stdout , stderr ) = ShellRunner .RunPowerShell (script , dryRun );
264+
265+ // ❌ BAD — CS8132: only deconstructing 2 of 3 values
266+ var (exitCode , output ) = ShellRunner .RunPowerShell (script , dryRun );
267+ ```
268+
269+ ---
270+
271+ ## Batch Editing Workflow — Verify File Anchors
272+
273+ When making bulk edits across many files (e.g., restoring 453 tweaks):
274+
275+ 1 . Read the target file first to confirm exact content
276+ 2 . Use ` multi_replace_string_in_file ` for independent edits
277+ 3 . After each batch, verify the build: ` dotnet build `
278+ 4 . Commit per logical phase (e.g., per 10 modules)
279+
280+ ** Common trap** : File contents change between sessions (e.g., formatter runs, manual edits).
281+ Always re-read before editing — never assume content matches what was seen earlier.
282+
283+ ---
284+
285+ ## SetExpandString and SetQword — Less Common RegOp Factories
286+
287+ ` RegOp.SetExpandString ` and ` RegOp.SetQword ` exist but are rarely used.
288+ When a registry value contains ` %SystemRoot% ` or other environment variables,
289+ use ` SetExpandString ` (REG_EXPAND_SZ), not ` SetString ` (REG_SZ).
290+
291+ ``` csharp
292+ // ✅ GOOD — REG_EXPAND_SZ preserves environment variable expansion
293+ RegOp .SetExpandString (@" HKLM\..." , " ImagePath" , @" %SystemRoot%\System32\svchost.exe -k netsvcs" )
294+
295+ // ❌ BAD — REG_SZ won't expand %SystemRoot% at runtime
296+ RegOp .SetString (@" HKLM\..." , " ImagePath" , @" %SystemRoot%\System32\svchost.exe -k netsvcs" )
297+ ```
298+
299+ ---
300+
301+ ## IsApplicable — Hardware Gating for Tweaks
302+
303+ Tweaks that target specific software (Chrome, Firefox, Java, Docker) or hardware
304+ (NVIDIA GPU, WSL, Hyper-V) should set ` IsApplicable ` to grey them out in the GUI:
305+
306+ ``` csharp
307+ new TweakDef
308+ {
309+ Id = " chrome-disable-translate" ,
310+ IsApplicable = () => HardwareInfo .IsChromeInstalled (),
311+ ApplicabilityNote = " Google Chrome is not installed" ,
312+ .. .
313+ }
314+ ```
315+
316+ ` TweakEngine.IsApplicableOnHardware() ` checks custom predicates first,
317+ then auto-detects from category (WSL, Virtualization) and tags (nvidia).
318+ MainForm caches results in ` _inapplicableIds ` at startup.
0 commit comments