|
| 1 | +# Field Test #10: Just Perfection |
| 2 | + |
| 3 | +## Pre-flight |
| 4 | + |
| 5 | +- **Extension**: Just Perfection (`just-perfection-desktop@just-perfection`) |
| 6 | +- **Source**: https://github.com/jrahmatzadeh/just-perfection |
| 7 | +- **GNOME versions**: 45, 46, 47, 48, 49, 50 |
| 8 | +- **File count**: 7 JS files, 2 CSS files; ~5,300 JS lines (Manager.js alone is 1,636 non-blank) |
| 9 | +- **License**: GPL-3.0-only (in repo root, not in `src/`) |
| 10 | +- **Why this extension**: Most popular GNOME extension; exercises connectObject/disconnectObject signal management (67 signals), prototype backup/restore via `#originals` map, `src/` directory layout, GNOME 50 support (widest version range), CSS-heavy (23.7%), private field usage (`#timeoutIds`, `#originals`, `#shellVersion`), 20 Shell.ui imports |
| 11 | + |
| 12 | +## Step 1: ego-lint |
| 13 | + |
| 14 | +```bash |
| 15 | +./ego-lint --verbose /tmp/just-perfection/src |
| 16 | +``` |
| 17 | + |
| 18 | +### Results (before fixes) |
| 19 | + |
| 20 | +| Status | Count | |
| 21 | +|--------|-------| |
| 22 | +| PASS | 202 | |
| 23 | +| FAIL | 3 | |
| 24 | +| WARN | 414 | |
| 25 | +| SKIP | 12 | |
| 26 | +| Exit | 1 | |
| 27 | + |
| 28 | +### Classification of Each FAIL |
| 29 | + |
| 30 | +| Rule | File:Line | TP/FP | Root Cause (if FP) | |
| 31 | +|------|-----------|-------|-------------------| |
| 32 | +| `license` | — | **FP** | LICENSE in repo root, not in `src/`; no parent-dir fallback for src/ layout | |
| 33 | +| `R-VER48-07` | stylesheet.css:167 | TP | `.quick-menu-toggle` renamed to `.quick-toggle-has-menu` in GNOME 48 | |
| 34 | +| `metadata/future-shell-version` | — | TP | GNOME 50 > CURRENT_STABLE (49) | |
| 35 | + |
| 36 | +### Classification of Key WARNs |
| 37 | + |
| 38 | +| Rule | Count | Classification | Notes | |
| 39 | +|------|-------|---------------|-------| |
| 40 | +| R-SLOP-01 (JSDoc @param) | 129 | **FP** | Provenance score=3 but threshold was >=4; PR #23 fixes threshold to >=3 | |
| 41 | +| R-SLOP-02 (JSDoc @returns) | 271 | **FP** | Same root cause as R-SLOP-01 | |
| 42 | +| `lifecycle/prototype-override` | 5 (3 unique) | TP + **bug** | Advisory is valid (prototypes restored via close() chain). Regex catches both override AND restore → duplicates | |
| 43 | +| `metadata/uuid-matches-dir` | 1 | **FP** | Dir is `src`, not UUID; meaningless for src/ layout | |
| 44 | +| `metadata/session-modes-consistency` | 1 | **FP** | `sessionMode.isLocked` used as guard — not lock screen functionality | |
| 45 | +| `quality/impossible-state` | 1 | **FP** | Same isLocked guard pattern | |
| 46 | +| `quality/comment-density` | 1 | **FP** | SupportNotifier.js has 40% comments from thorough hand-written JSDoc | |
| 47 | +| `metadata/deprecated-version` | 1 | TP | `version` field ignored by EGO for GNOME 45+ | |
| 48 | +| `quality/file-complexity` | 1 | TP | Manager.js 1,636 non-blank lines | |
| 49 | +| `quality/private-api` | 1 | TP | statusArea access (legitimate for a UI tweaker) | |
| 50 | +| `disclosure/private-api` | 1 | TP | Private API not disclosed in metadata description | |
| 51 | + |
| 52 | +## Fixes Implemented |
| 53 | + |
| 54 | +Split across 3 PRs per one-concern-per-PR convention: |
| 55 | + |
| 56 | +### PR: fix/src-layout-license (closes #26) |
| 57 | + |
| 58 | +| Rule/Check | Root Cause | Fix | |
| 59 | +|------------|-----------|-----| |
| 60 | +| `license` (FAIL) | No parent-dir fallback for src/ layout | `ego-lint.sh`: check parent dir when `basename == "src"` | |
| 61 | +| `metadata/uuid-matches-dir` | Dir is `src` for src/ layout | `check-metadata.py`: skip when `dir_name == "src"` | |
| 62 | + |
| 63 | +### PR: fix/islocked-guard (closes #27) |
| 64 | + |
| 65 | +| Rule/Check | Root Cause | Fix | |
| 66 | +|------------|-----------|-----| |
| 67 | +| `session-modes-consistency` | `isLocked` is always a guard | `check-metadata.py`: narrow regex to `sessionMode.currentMode` only | |
| 68 | +| `quality/impossible-state` | `isLocked` is always a guard | `check-quality.py`: remove `isLocked` from check, keep `currentMode` comparisons | |
| 69 | +| `quality/comment-density` | 40% threshold too aggressive | `check-quality.py`: raise threshold from 40% to 50% | |
| 70 | + |
| 71 | +### PR: fix/proto-override-dedup (closes #28) |
| 72 | + |
| 73 | +| Rule/Check | Root Cause | Fix | |
| 74 | +|------------|-----------|-----| |
| 75 | +| `lifecycle/prototype-override` (dupes) | Regex matches override + restore | `check-lifecycle.py`: deduplicate by `(file, prototype)` key | |
| 76 | + |
| 77 | +### Test Fixtures Added |
| 78 | + |
| 79 | +| Fixture | What It Tests | |
| 80 | +|---------|--------------| |
| 81 | +| `src-license-fallback@test` | License found in parent dir for src/ layout; UUID-dir skip | |
| 82 | +| `islocked-guard@test` | `sessionMode.isLocked` guard not flagged as impossible-state or session-modes inconsistency | |
| 83 | +| `proto-override-dedup@test` | Each prototype warned only once despite override + restore pattern | |
| 84 | + |
| 85 | +### Existing Fixture Updated |
| 86 | + |
| 87 | +| Fixture | Change | Reason | |
| 88 | +|---------|--------|--------| |
| 89 | +| `ai-slop@test` | `sessionMode.isLocked` → `sessionMode.currentMode !== 'unlock-dialog'` | `isLocked` no longer triggers impossible-state (by design) | |
| 90 | + |
| 91 | +## Results (after all fixes) |
| 92 | + |
| 93 | +| Status | Before | After | Change | |
| 94 | +|--------|--------|-------|--------| |
| 95 | +| FAIL | 3 | 2 | -1 (license FP fixed) | |
| 96 | +| WARN | 414 | 408 | -6 (5 FPs + 2 dupes fixed) | |
| 97 | + |
| 98 | +**With PR #23 merged** (provenance threshold >=3): WARNs would drop to ~8, all true positives. |
| 99 | + |
| 100 | +## Calibration Lessons Learned |
| 101 | + |
| 102 | +1. **`sessionMode.isLocked` is always a guard**: Reading lock state to decide behavior is defensive coding, not lock screen functionality. Only `currentMode === 'unlock-dialog'` comparisons suggest active lock screen mode usage. |
| 103 | + |
| 104 | +2. **`src/` layout needs holistic support**: License check and UUID-dir match didn't handle src/ layout. Multiple checks already had src/ fallbacks (CSS, prefs, metadata), but these two were missed. |
| 105 | + |
| 106 | +3. **Prototype override + restore creates duplicates**: When an extension stores originals and restores them (Just Perfection's `#originals` map pattern), the same regex catches both the override and the restore. Deduplication by `(file, prototype_name)` is essential. |
| 107 | + |
| 108 | +4. **Comment-density threshold interacts with provenance**: Well-documented hand-written code (provenance=3) naturally has higher comment density (40%+) from thorough JSDoc. The 40% threshold was too aggressive; 50% avoids FPs while still catching AI slop (typically 55-70%). |
| 109 | + |
| 110 | +5. **Just Perfection validates PR #23**: Provenance score=3 with 400 JSDoc warnings confirms the threshold change from >=4 to >=3 is needed. |
0 commit comments