You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Gap Analysis: EGO Review Guidelines vs Plugin Coverage
Date: 2026-02-25
Method: Every MUST requirement from requirements-reference.md was checked against the plugin's Tier 1 pattern rules (rules/patterns.yaml), Tier 2 scripts (skills/ego-lint/scripts/), and Tier 3 checklists (skills/ego-review/references/).
Legend
Covered: An automated check (Tier 1 or Tier 2) directly enforces this requirement.
Partial: A check exists but only catches some cases or uses heuristics that can miss violations.
Tier 3 Only: Covered by a review checklist read by Claude during ego-review, but no automated check.
Uncovered: No automated check and no checklist item addresses this requirement.
Section 1: Initialization and Lifecycle
Guideline Requirement
Severity
Currently Covered?
By Which Rule/Check?
Gap Notes
MUST NOT create objects during initialization (constructor/import time)
Only checks constructor bodies for known bad patterns (getSettings, connect, timeout_add, DBusProxy). Does NOT detect GObject creation (e.g., new St.Widget(), new Gio.Settings()) in constructors. Does not check module-level code (import-time side effects).
Checklist covers nulling references. Automated check warns when .destroy() is not followed by = null on the same variable. Does not cover all memory clearing scenarios.
If run_dispose() is used, MUST include comment explaining why
Checks if return values are assigned AND verifies GLib.Source.remove() is called in disable() for stored IDs.
Sources MUST be removed even if callback returns GLib.SOURCE_REMOVE
MUST
Tier 3 Only
lifecycle-checklist.md
Checklist mentions this. No automated verification.
Section 5: Library and Import Restrictions
Guideline Requirement
Severity
Currently Covered?
By Which Rule/Check?
Gap Notes
MUST NOT import Gdk in Shell process
MUST
Covered
R-IMPORT-02, check-imports.sh
Checks gi://Gdk in extension.js and lib/**/*.js.
MUST NOT import Gtk in Shell process
MUST
Covered
R-IMPORT-01, check-imports.sh
Checks gi://Gtk in extension.js and lib/**/*.js.
MUST NOT import Adw in Shell process
MUST
Covered
R-IMPORT-03, check-imports.sh
Checks gi://Adw in extension.js and lib/**/*.js.
MUST NOT import Clutter in preferences
MUST
Covered
R-IMPORT-04, check-imports.sh
Checks gi://Clutter in prefs.js.
MUST NOT import Meta in preferences
MUST
Covered
R-IMPORT-05, check-imports.sh
Checks gi://Meta in prefs.js.
MUST NOT import St in preferences
MUST
Covered
R-IMPORT-06, check-imports.sh
Checks gi://St in prefs.js.
MUST NOT import Shell in preferences
MUST
Covered
R-IMPORT-07, check-imports.sh
Checks gi://Shell in prefs.js.
Section 6: Deprecated Modules
Guideline Requirement
Severity
Currently Covered?
By Which Rule/Check?
Gap Notes
MUST NOT import ByteArray
MUST
Covered
R-DEPR-03, ego-lint.sh no-deprecated-modules
Both pattern rule and inline check.
MUST NOT import Lang
MUST
Covered
R-DEPR-02, ego-lint.sh no-deprecated-modules
Both pattern rule and inline check.
MUST NOT import Mainloop
MUST
Covered
R-DEPR-01, ego-lint.sh no-deprecated-modules
Both pattern rule and inline check.
MUST NOT use imports.misc.extensionUtils
MUST
Covered
R-DEPR-05
Pattern matches ExtensionUtils.
Section 7: Code Quality and Readability
Guideline Requirement
Severity
Currently Covered?
By Which Rule/Check?
Gap Notes
Code MUST NOT be minified
MUST
Covered
R-FILE-06, ego-lint.sh minified-js
Checks for lines > 500 chars and webpack boilerplate.
Code MUST NOT be obfuscated
MUST
Partial
R-FILE-06 (minified-js)
Minification check catches some obfuscation (long lines). No specific check for obfuscation techniques (encoded strings, variable mangling without long lines).
TypeScript MUST be transpiled to well-formatted JavaScript
MUST
Partial
R-FILE-06
Would catch poorly-transpiled TS (minified output). Well-formatted but clearly machine-generated TS output is not flagged.
Warns on future versions and multiple dev releases. Does NOT validate that entries are actual released GNOME versions (e.g., would not reject "99" or "37").
MUST NOT claim support for future versions
MUST
Partial
R-META-17 (check-metadata.py)
Issues WARN (not FAIL) for versions > current stable. Guidelines say this is a hard reject.
url field required for EGO
MUST
Partial
R-META-22 (check-metadata.py)
Issues WARN, not FAIL. Guidelines say MUST for EGO submission.
session-modes MUST be dropped if only ["user"]
MUST
Partial
R-META-09 (check-metadata.py)
Issues WARN, not FAIL. Guidelines explicitly call this a hard reject.
donations MUST only contain valid keys
MUST
Covered
R-META-18 (check-metadata.py)
FAIL on invalid keys.
donations MUST be dropped if not used
MUST
Covered
R-META-24 (check-metadata.py)
FAIL on empty donations.
version-name format validation
MUST
Covered
R-META-20 (check-metadata.py)
Validates 1-16 char regex.
Section 10: GSettings Schema Requirements
Guideline Requirement
Severity
Currently Covered?
By Which Rule/Check?
Gap Notes
Schema ID MUST use org.gnome.shell.extensions as base
MUST
Covered
R-SCHEMA-02, R-META-10, check-schema.sh
Validated in both metadata and schema XML.
Schema path MUST use /org/gnome/shell/extensions/ as base
MUST
Covered
R-SCHEMA-03, check-schema.sh
Validates path prefix and trailing slash.
Schema XML file MUST be included if settings-schema declared
MUST
Covered
R-SCHEMA-01, check-schema.sh
FAIL if metadata declares schema but no XML found.
Schema XML filename MUST follow <schema-id>.gschema.xml
Scripts MUST be written in GJS unless absolutely necessary
MUST
Covered
ego-lint.sh non-gjs-scripts
FAIL for non-GJS scripts without pkexec justification; WARN with pkexec (privileged helper exception).
MUST NOT include binary executables or libraries
MUST
Covered
R-FILE-04, ego-lint.sh no-binary-files
Scripts MUST be distributed under OSI-approved license
MUST
Tier 3 Only
licensing-checklist.md
Requires manual license review of included scripts.
MUST NOT use synchronous subprocess calls in Shell process
MUST
Covered
R-SEC-14 (pattern: sync subprocess), R-DEPR-08 (upgraded to blocking)
Detects spawn_sync, GLib.spawn_command_line_sync, and other synchronous subprocess patterns. Upgraded to FAIL severity as sync calls block the compositor.
Section 14: Session Modes
Guideline Requirement
Severity
Currently Covered?
By Which Rule/Check?
Gap Notes
Using unlock-dialog MUST be necessary for correct operation
MUST
Tier 3 Only
lifecycle-checklist.md
Requires semantic understanding of why lock screen access is needed.
All keyboard event signals MUST be disconnected in lock screen mode
MUST
Covered
R-LIFE-11 (check-lifecycle.py lockscreen-signals)
Detects keyboard signals (key-press-event, key-release-event, captured-event) without session mode guards when unlock-dialog is declared.
disable() function MUST include comment explaining why unlock-dialog is used
MUST
Covered
R-LIFE-14 (check-lifecycle.py)
Warns when unlock-dialog declared but disable() has no explanatory comment.
Extensions MUST NOT disable selectively
MUST
Covered
R-LIFE-13 (check-lifecycle.py)
Detects if (...) return; in disable() that skips cleanup.
session-modes field MUST be dropped if only using user
MUST
Partial
R-META-09 (check-metadata.py)
Issues WARN, not FAIL. Should be FAIL per guidelines.
Section 15: Licensing and Attribution
Guideline Requirement
Severity
Currently Covered?
By Which Rule/Check?
Gap Notes
MUST be distributed under terms compatible with GPL-2.0-or-later
MUST
Partial
R-FILE-03, ego-lint.sh license
Checks for LICENSE/COPYING file existence (WARN if missing). Does NOT validate license content/compatibility.
Code from other extensions MUST include original author attribution
MUST
Tier 3 Only
licensing-checklist.md (L2)
Requires semantic analysis to detect borrowed code.
Attribution MUST be in distributed files (not just repo)
MUST
Tier 3 Only
licensing-checklist.md (L2)
Requires semantic review.
Section 16: Content and Code of Conduct
Guideline Requirement
Severity
Currently Covered?
By Which Rule/Check?
Gap Notes
MUST NOT violate GNOME Code of Conduct
MUST
Tier 3 Only
licensing-checklist.md (L5)
Requires semantic content review. Not automatable.
MUST NOT promote political agendas
MUST
Tier 3 Only
licensing-checklist.md (L4)
Requires semantic content review. Not automatable.
MUST NOT include copyrighted content without permission
MUST
Tier 3 Only
licensing-checklist.md (L3)
Requires asset review. Not automatable.
MUST NOT include trademarked content without permission
MUST
Tier 3 Only
licensing-checklist.md (L3)
Requires asset review. Not automatable.
Section 17: Functionality Requirements
Guideline Requirement
Severity
Currently Covered?
By Which Rule/Check?
Gap Notes
Extensions that are fundamentally broken MUST be rejected
MUST
Uncovered
--
Requires runtime testing. Not feasible for static analysis.
Extensions with no purpose or functionality MUST be rejected
MUST
Uncovered
--
Requires semantic understanding of extension purpose.
Section 21: Preferences (prefs.js)
Guideline Requirement
Severity
Currently Covered?
By Which Rule/Check?
Gap Notes
MUST extend ExtensionPreferences class
MUST
Partial
R-PREFS-02 (check-prefs.py default-export)
Checks for export default class but does NOT verify it extends ExtensionPreferences.
MUST implement fillPreferencesWindow() or getPreferencesWidget()
MUST
Covered
R-PREFS-01 (check-prefs.py)
FAIL if neither method is present. Detects dual-prefs pattern conflict.
These are known false positives and high-noise warnings identified by running ego-lint against hara-hachi-bu, an 11-module extension used as the regression baseline. Each item includes the root cause and a suggested improvement.
Rule / Check
Description
Impact
Suggested Fix
R-PREFS-04b (GTK widget spam)
Every new Gtk.Label(), Gtk.Button(), etc. fires WARN even inside Adw containers. No Adw replacement exists for these widgets.
~43 warnings (48% of output)
Whitelist GTK widgets with no Adw equivalent, or deduplicate to one summary warning
R-PREFS-04 (Gtk.ListBox)
Gtk.ListBox flagged as blocking, but is valid inside Adw.PreferencesGroup for dynamic lists
1 false FAIL
Downgrade to advisory, or suppress when Adw.PreferencesGroup present in same file
R-SEC-20 (pkexec repetition)
Every pkexec string fires WARN across JS, SH, and packaging scripts
~10 identical warnings
Deduplicate to one summary, or correlate with polkit policy presence
Real-world EGO rejections that informed the plugin's detection rules:
Search Light (May 2024) -- Lifecycle Violations
Rejection reason: Signals connected in enable() were not fully disconnected in disable(). Search provider was registered but not unregistered, leading to crashes when the extension was disabled mid-search.
Blur my Shell (March 2024) -- Init-Time Violations
Rejection reason: GObject creation (new Gio.Settings()) detected in the extension constructor rather than in enable(). Module-level code was creating Shell modifications at import time.
Rejection reason: Used GLib.spawn_command_line_sync() to invoke external commands, blocking the compositor. Also included unnecessary metadata fields that were not part of the specification.
Relevant rules: R-SEC-14 (sync subprocess pattern), R-DEPR-08 (blocking subprocess upgraded to FAIL), check-metadata.py (unknown field detection)
Power Tracker (September 2024) -- Missing URL
Rejection reason: Missing url field in metadata.json. EGO requires this field for all submissions to provide users with a link to the extension's source code or homepage.
Relevant rules: R-META-22 (missing url, now FAIL)
Open Bar (February 2024) -- Orphaned Signals, Missing Timeout Cleanup
Rejection reason: Multiple signal connections in helper modules were never disconnected because the cleanup code only covered the main extension file. Timeouts created in a utility module were not tracked or removed in disable().