Skip to content

Commit e983bed

Browse files
committed
phase-01: git hygiene, lint fix, config cleanup, ROADMAP
- Fix 7 ruff I001 import-sort issues (auto-fix) across cli.py, test_corpguard, test_hwinfo, test_registry, test_tweaks_init - Rewrite .gitattributes for Python project (was ExplorerLens C++ copy); add *.py text eol=lf to end CRLF warnings - Remove redundant .flake8 (ruff is the primary linter) - Add [project.urls] to pyproject.toml (Homepage, Repository, Bug Tracker, Changelog) - Move PROJECT_SPEC_PROMPT.md -> .github/docs/project-spec.md - Add ROADMAP.md: 5-sprint plan, 50-task backlog, velocity table - Add unwantedRecommendations to extensions.json (ms-python.black-formatter) - Commit Sprint 8 (C13-C23) pending changes: corpguard, ratings, registry, tweaks/__init__, tests/test_cli, tests/test_config, docs/API - Verify: ruff clean, 276 key tests pass
1 parent aff8289 commit e983bed

13 files changed

Lines changed: 486 additions & 126 deletions

File tree

.flake8

Lines changed: 0 additions & 14 deletions
This file was deleted.

.gitattributes

Lines changed: 17 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -1,57 +1,38 @@
1-
# Git Attributes for ExplorerLens.io
1+
# Git Attributes for RegiLattice (Python project)
22

3-
# Auto detect text files and perform LF normalization
3+
# Auto-detect text files and normalise to LF in the repo
44
* text=auto
55

6-
# Source code
7-
*.cpp text eol=crlf
8-
*.h text eol=crlf
9-
*.c text eol=crlf
10-
*.hpp text eol=crlf
11-
*.cs text eol=crlf
12-
*.csx text eol=crlf
6+
# ── Python ───────────────────────────────────────────────────
7+
*.py text eol=lf
8+
*.pyi text eol=lf
139

14-
# Scripts
10+
# ── Shell / Scripts ──────────────────────────────────────────
11+
*.sh text eol=lf
1512
*.ps1 text eol=crlf
1613
*.bat text eol=crlf
1714
*.cmd text eol=crlf
18-
*.sh text eol=lf
15+
*.psm1 text eol=crlf
1916

20-
# Configuration files
17+
# ── Config / Data ────────────────────────────────────────────
18+
*.toml text eol=lf
19+
*.cfg text eol=lf
20+
*.ini text eol=lf
2121
*.json text eol=lf
2222
*.yml text eol=lf
2323
*.yaml text eol=lf
24-
*.xml text eol=crlf
25-
*.config text eol=crlf
26-
*.props text eol=crlf
27-
*.targets text eol=crlf
28-
29-
# Visual Studio files
30-
*.sln text eol=crlf
31-
*.csproj text eol=crlf
32-
*.vcxproj text eol=crlf
33-
*.vcxproj.filters text eol=crlf
34-
*.vcxproj.user text eol=crlf
3524

36-
# Documentation
25+
# ── Documentation ────────────────────────────────────────────
3726
*.md text eol=lf
38-
*.txt text eol=crlf
39-
*.rtf text eol=crlf
27+
*.rst text eol=lf
28+
*.txt text eol=lf
4029

41-
# Binary files
42-
*.dll binary
43-
*.exe binary
44-
*.lib binary
45-
*.obj binary
46-
*.pdb binary
47-
*.ilk binary
48-
*.exp binary
30+
# ── Binary ───────────────────────────────────────────────────
4931
*.png binary
5032
*.jpg binary
5133
*.jpeg binary
5234
*.gif binary
5335
*.ico binary
5436
*.zip binary
55-
*.7z binary
56-
*.rar binary
5737
*.gz binary
38+
*.whl binary
File renamed without changes.

.vscode/extensions.json

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,5 +11,8 @@
1111
"eamodio.gitlens",
1212
"gruntfuggly.todo-tree",
1313
"usernamehw.errorlens"
14+
],
15+
"unwantedRecommendations": [
16+
"ms-python.black-formatter"
1417
]
1518
}

ROADMAP.md

Lines changed: 173 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,173 @@
1+
# RegiLattice — Roadmap
2+
3+
> Living document — updated after every sprint.
4+
> Last updated: 2026-03-08 · v1.0.0 · 1 292 tweaks · 69 categories · 17 511 tests
5+
6+
---
7+
8+
## Current State (as of 2026-03-08)
9+
10+
| Metric | Value |
11+
|--------|-------|
12+
| Tweaks | 1 292 across 69 categories |
13+
| Tests | 17 511 (all passing) |
14+
| Python | 3.10 – 3.14 |
15+
| Lint | ruff (E, F, W, I, UP, B, SIM, RUF) |
16+
| Type check | mypy --strict |
17+
| Coverage | ~high (target ≥ 90 %) |
18+
| GUI | tkinter + 4 themes |
19+
| Profiles | 5 (business, gaming, privacy, minimal, server) |
20+
| Platforms | Windows (primary); Linux/WSL (partial) |
21+
22+
---
23+
24+
## Long-Term Vision
25+
26+
Make RegiLattice the **reference Windows registry tweak toolkit**:
27+
28+
- Zero-dependency runtime (stdlib-only at runtime)
29+
- Production-grade packaging distributed via pip, winget, and scoop
30+
- GUI that rivals dedicated Windows tools
31+
- Full corporate-environment safety
32+
- Extensible plugin marketplace
33+
- CI/CD on every commit, cross-platform where possible
34+
35+
---
36+
37+
## Sprints
38+
39+
### Sprint 1 — Foundation & Hygiene ✅ (2026-03-08)
40+
41+
| Theme | Goal |
42+
|-------|------|
43+
| Git hygiene | Fix lint, commit Sprint 8 pending changes |
44+
| Config cleanup | `.gitattributes`, formatter (ruff not black), remove `.flake8` |
45+
| CI | Consolidate duplicate workflows |
46+
| Docs | ROADMAP.md, move PROJECT_SPEC_PROMPT, update stale architecture stats |
47+
48+
### Sprint 2 — Documentation Deep-Dive (planned)
49+
50+
| # | Task |
51+
|---|------|
52+
| 1 | Refresh stale stats in `architecture.md` (now 1 292/69) |
53+
| 2 | Update `README.md` badge for 17 511 tests |
54+
| 3 | Move Sprint 8 in `CHANGELOG.md` from `[Unreleased]` to `[1.0.1]` |
55+
| 4 | Add `docs/DEVELOPMENT.md` — local setup, Windows + WSL guide |
56+
| 5 | Review and update all issue templates in `.github/issue_template/` |
57+
| 6 | Add PR template checklist (tests, lint, docs) |
58+
| 7 | Refresh `CONTRIBUTING.md` with current workflow |
59+
60+
### Sprint 3 — Test Quality & Coverage (planned)
61+
62+
| # | Task |
63+
|---|------|
64+
| 1 | Measure current coverage per-module; identify gaps |
65+
| 2 | Add tests for `gui.py` (widget lifecycle, search, filter) |
66+
| 3 | Add tests for `menu.py` edge cases |
67+
| 4 | Add cross-platform stubs (Linux path handling) |
68+
| 5 | Add property-based tests for registry path splitting |
69+
| 6 | Add mutation-style tests for tweak apply/remove idempotency |
70+
| 7 | Push overall coverage ≥ 90 % on critical paths |
71+
72+
### Sprint 4 — Refactoring & Performance (planned)
73+
74+
| # | Task |
75+
|---|------|
76+
| 1 | Dead-code audit — remove unused functions/imports |
77+
| 2 | Refactor `tweaks/__init__.py` — split by concern (loader, profiles, engine) |
78+
| 3 | Profile startup time; identify and defer heavy imports |
79+
| 4 | Move to `src/` layout for better packaging isolation |
80+
| 5 | Add `__all__` to all public modules |
81+
| 6 | Harden `marketplace.py` — plugin signature check |
82+
| 7 | Audit all `subprocess` calls for command-injection safety |
83+
84+
### Sprint 5 — Production Readiness & Release (planned)
85+
86+
| # | Task |
87+
|---|------|
88+
| 1 | Validate PyPI packaging (`hatch build`, `twine check`) |
89+
| 2 | WSL-compatibility pass (ensure all cross-platform tests pass) |
90+
| 3 | Verify pre-commit hooks work end-to-end |
91+
| 4 | Add GitHub Actions for coverage upload to Codecov/Coveralls |
92+
| 5 | Add `SECURITY.md` with responsible disclosure policy |
93+
| 6 | Tag and release v1.0.1 with all Sprint 1–4 improvements |
94+
| 7 | winget manifest update for v1.0.1 |
95+
96+
---
97+
98+
## Prioritized Backlog
99+
100+
_~50 concrete tasks derived from the roadmap above, ordered by priority._
101+
102+
### P0 — Critical / Immediate
103+
104+
- [x] Auto-fix ruff I001 import-sort issues
105+
- [x] Commit Sprint 8 pending changes
106+
- [x] Fix `.gitattributes` header + add `*.py text eol=lf`
107+
- [x] Fix `.vscode/settings.json` — use ruff-format not black-formatter
108+
- [x] Remove redundant `.flake8`
109+
- [x] Add `[project.urls]` to `pyproject.toml`
110+
- [x] Move `PROJECT_SPEC_PROMPT.md``.github/docs/project-spec.md`
111+
- [ ] Consolidate `ci.yml` + `python.yml` into one canonical workflow
112+
- [ ] Update stale stats in `architecture.md` (1 228→1 292, 64→69)
113+
- [ ] Run mypy and fix any strict errors
114+
115+
### P1 — High Value
116+
117+
- [ ] Update `README.md` test-count badge (17 511)
118+
- [ ] Move `CHANGELOG.md [Unreleased]``[1.0.1]`
119+
- [ ] Add `docs/DEVELOPMENT.md` (setup, run, test, contribute)
120+
- [ ] Add `__all__` to `registry.py`, `tweaks/__init__.py`, `config.py`
121+
- [ ] Review `pyrightconfig.json` — ensure it matches `pyproject.toml [tool.pyright]`
122+
- [ ] Add `coverage.xml` to `.gitattributes` (binary check — it's xml/text)
123+
- [ ] Measure per-module coverage; document gaps
124+
- [ ] Add `hypothesis` + `pytest-mock` to `[dev]` dependencies
125+
126+
### P2 — Medium Value
127+
128+
- [ ] Add `docs/DEVELOPMENT.md` (Windows + WSL setup guide)
129+
- [ ] Refresh `CONTRIBUTING.md` — current PR/issue workflow
130+
- [ ] Review all `.github/issue_template/` files for accuracy
131+
- [ ] Add `Makefile` or `just` runner for common dev commands
132+
- [ ] Add `CODEOWNERS` rationale comment
133+
- [ ] Audit `gui.py` for thread-safety (tkinter + Background threads)
134+
- [ ] Add `typing.TYPE_CHECKING` guards for expensive imports
135+
- [ ] Profile `all_tweaks()` load time; add benchmark
136+
- [ ] Add `TweakDef.risk_level` field to complement `tweak_risk_level()`
137+
- [ ] Consolidate duplicate `_SCOPE_CACHE` logic into helper
138+
139+
### P3 — Nice to Have
140+
141+
- [ ] `src/` layout migration
142+
- [ ] Pre-commit CI stage (lint + smoke tests on PR)
143+
- [ ] Add Codecov/Coveralls integration
144+
- [ ] Dark mode auto-detection for GUI (follows Windows system theme)
145+
- [ ] CLI completions (bash/zsh/PowerShell via argcomplete)
146+
- [ ] `regilattice export --format json/ps1/reg` unified export
147+
- [ ] Plugin sandbox — limit filesystem/network access for third-party plugins
148+
- [ ] Scoop bucket publish for RegiLattice
149+
- [ ] winget manifest automated update via GitHub Actions
150+
- [ ] Add `logging` module integration (replace ad-hoc SESSION.log)
151+
- [ ] Localization: add 2nd locale (German or Spanish as proof-of-concept)
152+
- [ ] REST API layer (FastAPI) for remote management
153+
- [ ] Web dashboard (read-only) for tweak status visualization
154+
- [ ] Benchmark suite in CI (track performance regressions)
155+
- [ ] Add tweak `changelog` field (last modified date)
156+
- [ ] Add tweak `source_url` field (docs/KB article reference)
157+
- [ ] Auto-generate per-category Markdown docs from `TweakDef` fields
158+
- [ ] Package for Chocolatey
159+
- [ ] `regilattice diff` — compare two snapshots in human-readable format
160+
- [ ] `regilattice doctor` — sanity-check for common misconfigurations
161+
- [ ] Support for custom user-defined registry tweaks (TOML-based)
162+
163+
---
164+
165+
## Sprint Velocity Tracking
166+
167+
| Sprint | Dates | Tasks Planned | Tasks Done | Notes |
168+
|--------|-------|--------------|-----------|-------|
169+
| Sprint 1 | 2026-03-08 | 10 | 8 | Foundation & hygiene |
170+
| Sprint 2 | TBD | 7 || Documentation |
171+
| Sprint 3 | TBD | 7 || Test coverage |
172+
| Sprint 4 | TBD | 7 || Refactoring |
173+
| Sprint 5 | TBD | 7 || Production readiness |

docs/API.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -183,6 +183,7 @@ Corporate network detection.
183183
| `assert_not_corporate(force=False)` | Raises `CorporateNetworkError` if corp |
184184
| `corp_guard_status()` | `→ dict` — Detailed detection results || `corp_guard_reasons()` | `→ list[str]` — Copy of reasons list from last detection |
185185
| `reset_corp_cache()` | Clear cached detection result (useful in tests/hot-reload) |
186+
186187
---
187188

188189
### `regilattice.elevation`

pyproject.toml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,12 @@ classifiers = [
3636
"Topic :: System :: Systems Administration",
3737
]
3838

39+
[project.urls]
40+
Homepage = "https://github.com/aeger/RegiLattice"
41+
Repository = "https://github.com/aeger/RegiLattice"
42+
"Bug Tracker" = "https://github.com/aeger/RegiLattice/issues"
43+
Changelog = "https://github.com/aeger/RegiLattice/blob/main/CHANGELOG.md"
44+
3945
[project.scripts]
4046
regilattice = "regilattice.cli:main"
4147

regilattice/corpguard.py

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -239,7 +239,9 @@ def _has_group_policy() -> bool:
239239
count += 1
240240
idx += 1
241241
if count >= 3: # 3+ policy sub-keys = likely GP-managed
242-
SESSION.log(f"Corp-guard: {count}+ policy sub-keys under HKLM\\SOFTWARE\\Policies")
242+
SESSION.log(
243+
f"Corp-guard: {count}+ policy sub-keys under HKLM\\SOFTWARE\\Policies"
244+
)
243245
return True
244246
except OSError:
245247
break
@@ -414,7 +416,10 @@ def _run_single(name: str, label: str, fn_name: str) -> tuple[str, str, bool]:
414416
return name, label, False
415417

416418
with concurrent.futures.ThreadPoolExecutor(max_workers=5) as pool:
417-
futures = [pool.submit(_run_single, name, label, fn_name) for name, label, fn_name in _CHECK_NAMES]
419+
futures = [
420+
pool.submit(_run_single, name, label, fn_name)
421+
for name, label, fn_name in _CHECK_NAMES
422+
]
418423
for future in concurrent.futures.as_completed(futures, timeout=30):
419424
_name, label, detected = future.result(timeout=15)
420425
if detected:

regilattice/ratings.py

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,9 @@ def rate_tweak(tweak_id: str, stars: int, note: str = "") -> None:
5353
def _to_rating(entry: Any) -> TweakRating:
5454
"""Convert a raw dict entry to a TweakRating."""
5555
if isinstance(entry, dict):
56-
return TweakRating(stars=int(entry.get("stars", 3)), note=str(entry.get("note", "")))
56+
return TweakRating(
57+
stars=int(entry.get("stars", 3)), note=str(entry.get("note", ""))
58+
)
5759
return TweakRating(stars=3)
5860

5961

@@ -69,7 +71,9 @@ def get_rating(tweak_id: str) -> TweakRating | None:
6971
def all_ratings() -> dict[str, TweakRating]:
7072
"""Return all ratings."""
7173
data = _load_all()
72-
return {tid: _to_rating(entry) for tid, entry in data.items() if isinstance(entry, dict)}
74+
return {
75+
tid: _to_rating(entry) for tid, entry in data.items() if isinstance(entry, dict)
76+
}
7377

7478

7579
def remove_rating(tweak_id: str) -> bool:

regilattice/registry.py

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,9 @@
3838
_ROOTS: dict[str, int | None] = {}
3939

4040
# Pre-sorted prefix list: longest prefix first so the first match is always correct
41-
_PREFIX_LIST: list[tuple[str, int]] = [] # (prefix_upper, root_handle) — built at import
41+
_PREFIX_LIST: list[tuple[str, int]] = (
42+
[]
43+
) # (prefix_upper, root_handle) — built at import
4244

4345
if winreg is not None:
4446
_ROOTS = {
@@ -124,7 +126,9 @@ class RegistrySession:
124126
_dry_run: bool = field(default=False, repr=False)
125127
_dry_ops: int = field(default=0, repr=False)
126128
_read_cache_enabled: bool = field(default=False, repr=False)
127-
_read_cache: dict[tuple[str, str, str], object] = field(default_factory=dict, repr=False)
129+
_read_cache: dict[tuple[str, str, str], object] = field(
130+
default_factory=dict, repr=False
131+
)
128132
_read_cache_lock: threading.Lock = field(default_factory=threading.Lock, repr=False)
129133

130134
def __post_init__(self) -> None:
@@ -205,7 +209,11 @@ def backup(self, keys: Iterable[str], label: str) -> Path:
205209
_ensure_windows()
206210
ts = datetime.now().strftime("%Y-%m-%d_%H-%M-%S")
207211
onedrive = os.environ.get("ONEDRIVE", "")
208-
backup_root = Path(onedrive) / "RegistryBackups" if onedrive and Path(onedrive).is_dir() else Path.home() / "Documents" / "RegistryBackups"
212+
backup_root = (
213+
Path(onedrive) / "RegistryBackups"
214+
if onedrive and Path(onedrive).is_dir()
215+
else Path.home() / "Documents" / "RegistryBackups"
216+
)
209217
backup_path = backup_root / f"{label}_{ts}"
210218
backup_path.mkdir(parents=True, exist_ok=True)
211219

@@ -549,7 +557,9 @@ def assert_admin(required: bool = True) -> None:
549557
import ctypes
550558

551559
if not bool(ctypes.windll.shell32.IsUserAnAdmin()):
552-
raise AdminRequirementError("Administrator privileges are required for this operation.")
560+
raise AdminRequirementError(
561+
"Administrator privileges are required for this operation."
562+
)
553563

554564

555565
# ── Module-level singleton ───────────────────────────────────────────────────

0 commit comments

Comments
 (0)