diff --git a/A-Team-Android_ROM_Builder-v1.02.7z b/A-Team-Android_ROM_Builder-v1.02.7z new file mode 100644 index 0000000..27b8c53 Binary files /dev/null and b/A-Team-Android_ROM_Builder-v1.02.7z differ diff --git a/README-TECHNICAL.md b/README-TECHNICAL.md new file mode 100644 index 0000000..77a9450 --- /dev/null +++ b/README-TECHNICAL.md @@ -0,0 +1,1758 @@ +# A-Team Android ROM Builder — Technical Documentation + +## 1. Purpose + +A-Team Android ROM Builder is a Python/GTK 3 application that provides a graphical project-management layer around Android ROM development. + +The application is deliberately split into two major areas: + +1. **Python application/backend** + - GUI + - project state + - configuration loading + - environment generation + - profile management + - terminal integration + - resource monitoring + - host management + - updater handling + +2. **Bash/script layer** + - ROM synchronization + - device setup + - GApps synchronization + - ROM building + - cleaning + - uploading + - device-specific patches and setup + +This separation is one of the most important architectural characteristics of the project. + +The GUI should generally manage **what** project is being operated on, while scripts determine **how** the Android source tree is synchronized, modified, built, cleaned, or uploaded. + +--- + +## 2. High-Level Architecture + +```text + gui.py + | + +-------------+-------------+ + | | | + v v v + Project Configs UI Managers + | | | + +-------------+-------------+ + | + v + Project.as_environment() + | + v + Script / Action Layer + | + +------------+------------+ + | | | + v v v + sync.sh build.sh clean.sh + | + v + device sync scripts + | + v + Android ROM tree +``` + +The GUI owns project selections. + +The `Project` object converts those selections and configuration files into an environment that scripts consume. + +--- + +# 3. Main Application Entry Point + +The primary entry point is: + +```text +gui.py +``` + +The application initializes GTK, creates the `ROMBuilder` window, and constructs the application's tabs. + +The current interface contains: + +```text +1- Build Setup +2- Sync & Setup Device Source +3- Build +Terminal +Resource Monitor +Tools +``` + +The exact tab construction is contained in `ROMBuilder`. + +--- + +# 4. Python Backend + +The `builder/` directory contains the application backend. + +Current major modules include: + +```text +builder/ +├── actions.py +├── button_actions.py +├── config_loader.py +├── device_manager.py +├── hosts_manager.py +├── icon_manager.py +├── launcher_shortcut.py +├── profile_manager.py +├── project.py +├── project_loader.py +├── project_summary.py +├── resource_monitor.py +├── script_runner.py +├── splash.py +├── splash_manager.py +├── terminal.py +├── updater.py +├── updater_overlay.py +└── version.py +``` + +The backend is intentionally separated from GTK-specific code wherever practical. + +--- + +# 5. Configuration Loader + +`builder/config_loader.py` contains the basic configuration parser. + +It reads simple: + +```text +KEY=VALUE +``` + +files. + +Supported behavior includes: + +- Blank lines are ignored +- Lines beginning with `#` are comments +- Lines without `=` are ignored +- Values may be surrounded by single or double quotes +- `~` is expanded to the user's home directory + +Example: + +```text +DEVICE_CODENAME="milanf" +DEVICE_SOC="sm6375" +ROM_DISPLAY_NAME="LineageOS" +``` + +becomes a Python dictionary: + +```python +{ + "DEVICE_CODENAME": "milanf", + "DEVICE_SOC": "sm6375", + "ROM_DISPLAY_NAME": "LineageOS" +} +``` + +This deliberately simple format makes configuration files easy to edit from a terminal or text editor. + +--- + +# 6. Device Discovery + +Device discovery is handled by: + +```text +builder/device_manager.py +``` + +The application scans: + +```text +configs/devices/ +``` + +for `.conf` files. + +A device does not need to be hard-coded into the GUI. + +This means adding a properly formatted configuration file is the primary mechanism for adding a device. + +The device manager reads: + +```text +DEVICE_DISPLAY_NAME +``` + +for the user-facing device name. + +If it is not present, the configuration filename is used as a fallback display name. + +The device list is sorted by display name. + +--- + +# 7. Adding a New Device + +To add a new device, create: + +```text +configs/devices/.conf +``` + +For example: + +```text +configs/devices/example.conf +``` + +A practical device configuration should define the device identity and the variables required by its scripts. + +Example: + +```text +DEVICE_CODENAME="example" +DEVICE_DISPLAY_CODENAME="Example" +DEVICE_DISPLAY_NAME="Example Android Device" +DEVICE_KERNEL="5.4" +DEVICE_SOC="smXXXX" +DEVICE_MANUFACTURER="Motorola" +DEVICE_MODEL_NUMBER="XTXXXX" +DEVICE_SYNC_SCRIPT="example-sync.sh" +``` + +### Important variables + +#### `DEVICE_CODENAME` + +The Android/device-tree codename used by scripts. + +Example: + +```text +DEVICE_CODENAME="milanf" +``` + +#### `DEVICE_DISPLAY_CODENAME` + +Human-readable short name used in messages. + +```text +DEVICE_DISPLAY_CODENAME="Milanf" +``` + +#### `DEVICE_DISPLAY_NAME` + +Name shown in the GUI device selector. + +```text +DEVICE_DISPLAY_NAME="Moto G Stylus 5G 2022" +``` + +#### `DEVICE_SYNC_SCRIPT` + +Name of the device-specific synchronization script. + +```text +DEVICE_SYNC_SCRIPT="milanf-sync.sh" +``` + +The main `scripts/sync.sh` script uses this value to locate: + +```text +scripts/devices_sync/ +``` + +### Device-specific variables + +Any additional variables can be added to the device configuration. + +For example: + +```text +DEVICE_KERNEL="5.4" +DEVICE_SOC="sm6375" +DEVICE_MANUFACTURER="Motorola" +DEVICE_MODEL_NUMBER="XT2215" +``` + +Those values become part of the project environment and can therefore be consumed by Bash scripts. + +--- + +# 8. Device Sync Scripts + +Device-specific sync scripts live under: + +```text +scripts/devices_sync/ +``` + +A device configuration selects its script with: + +```text +DEVICE_SYNC_SCRIPT="example-sync.sh" +``` + +The main synchronization flow effectively becomes: + +```text +scripts/sync.sh + | + +--> load device configuration + | + +--> A-Team setup + | + +--> determine DEVICE_SYNC_SCRIPT + | + +--> cd "$ROM_PATH" + | + +--> run scripts/devices_sync/ +``` + +This allows each device to have completely different synchronization or patching requirements without turning the main GUI into a collection of device-specific conditionals. + +--- + +# 9. Project Object + +`builder/project.py` contains the `Project` dataclass. + +Important project state includes: + +```text +profile_name +host_name +device_name +rom_name +rom_branch +android_version +rom_path +build_variant +build_command +gapps_variant +clean_variant +installer_variant +build_jobs +use_ccache +custom_apn +device_vars +rom_vars +rom_config_path +setup_vars +upload_vars +``` + +This object is the central representation of the currently selected project. + +--- + +# 10. ROM Path Interpretation + +When a ROM source path is selected, `Project.set_rom_path()` derives: + +```text +ROM_BRANCH +ROM_NAME +``` + +from the directory structure. + +For a path such as: + +```text +/home/pizzag/Android/Roms/Lineage/23.2 +``` + +the project interprets: + +```text +ROM_NAME = Lineage +ROM_BRANCH = 23.2 +ROM_PATH = /home/pizzag/Android/Roms/Lineage/23.2 +``` + +This is important because the scripts receive these values automatically. + +--- + +# 11. ROM Configuration System + +There are two supported locations for the ROM configuration. + +### Application-level default + +```text +configs/rom.conf +``` + +### ROM-local override + +```text +/rom.conf +``` + +The loader checks the selected ROM root first. + +If: + +```text +/rom.conf +``` + +exists, it is loaded. + +Otherwise: + +```text +configs/rom.conf +``` + +is loaded. + +This allows a ROM tree to carry its own configuration. + +### Example + +Builder: + +```text +A-Team-Android_ROM_Builder/ +└── configs/ + └── rom.conf +``` + +ROM: + +```text +Lineage/ +└── 23.2/ + ├── build/ + ├── device/ + ├── vendor/ + └── rom.conf +``` + +The second file overrides the builder-level ROM configuration for that project. + +### Case sensitivity + +The loader currently checks for: + +```text +rom.conf +``` + +in lowercase. + +On Linux: + +```text +rom.conf +ROM.conf +Rom.conf +``` + +are different filenames. + +The build-command dropdown may display a human-readable entry such as: + +```text +Default --> Rom.conf +``` + +but the actual loader filename is: + +```text +rom.conf +``` + +--- + +# 12. ROM Configuration Variables + +The ROM configuration is not restricted to a fixed set of variables. + +Example: + +```text +M="make" + +CCACHE_SIZE="300" + +DEFAULT_ROM_BUILD_COMMAND="brunch $DEVICE_CODENAME" + +ROM_BUILD_NAME=lineage +ROM_TARGET_RELEASE="bp4a" +ROM_FINAL_LOCATION="~/Desktop/Release_Test" +ROM_BUILD_ZIP_NAME="*-UNOFFICIAL-$DEVICE_CODENAME.zip" +ROM_DISPLAY_NAME="LineageOS" +ROM_VENDOR_NAME=lineage +ROM_MANIFEST="https://github.com/LineageOS/android.git" +ROM_BRANCH_PREFIX="lineage-" +ROM_MAJOR_VERSION="23" +ROM_MINOR_VERSION="2" +``` + +Additional variables can be added when scripts require them. + +--- + +# 13. Variable Resolution + +`Project.as_environment()` combines several sources of variables. + +The environment begins with GUI/project values. + +Examples: + +```text +DEVICE_NAME +ROM_NAME +ROM_BRANCH +ROM_PATH +ANDROID_VERSION +BUILD_VARIANT +BUILD_COMMAND +GAPPS_VARIANT +CLEAN_VARIANT +INSTALLER_VARIANT +BUILD_JOBS +USE_CCACHE +APN_VARIANT +``` + +Then configuration dictionaries are merged: + +```text +device_vars +rom_vars +setup_vars +upload_vars +``` + +The project then resolves references such as: + +```text +$DEVICE_CODENAME +${DEVICE_CODENAME} +``` + +Nested variable references are supported through repeated resolution passes. + +This allows a ROM configuration to contain: + +```text +DEFAULT_ROM_BUILD_COMMAND="brunch $DEVICE_CODENAME" +``` + +without requiring Python code to know what the device codename is. + +--- + +# 14. Environment Precedence + +The environment is constructed approximately in this order: + +```text +Base project variables + | + v +Device variables + | + v +ROM variables + | + v +A-Team setup variables + | + v +Upload variables + | + v +Variable reference resolution +``` + +Therefore, configuration values should be named carefully to avoid unintentionally overriding a project variable. + +--- + +# 15. Build Commands + +The Build tab reads: + +```text +configs/rom_build_commands.conf +``` + +The current file can contain entries such as: + +```text +Default --> Rom.conf +Lineage +Derpfest +``` + +Lines beginning with `#` and blank lines are ignored. + +Entries containing: + +```text +--> +``` + +are treated as display-only entries by the current loader. + +Normal entries are converted into a lowercase command value. + +The selected command becomes: + +```text +BUILD_COMMAND +``` + +in the project environment. + +This makes it possible to expand the GUI's build command selector without modifying the Build tab itself. + +--- + +# 16. Build Execution + +The Build button calls the action layer. + +The action layer creates a temporary environment shell file containing the current project variables. + +Conceptually: + +```bash +export DEVICE_NAME='milanf' +export ROM_NAME='Lineage' +export ROM_BRANCH='23.2' +export ROM_PATH='/home/pizzag/...' +export ANDROID_VERSION='16' +... +``` + +The requested script is then executed. + +The build script is: + +```text +scripts/build.sh +``` + +The GUI therefore does not need to contain the ROM's actual build command logic. + +--- + +# 17. Script Execution + +`builder/script_runner.py` provides generic script execution. + +It: + +1. Copies the current process environment. +2. Adds `project.as_environment()`. +3. Verifies that the script exists. +4. Executes it with Bash. +5. Returns the exit status. + +The action layer provides another mechanism that is useful when the GUI needs a shell command containing the generated environment. + +This architecture allows scripts to remain independently testable. + +For example, a script can generally be debugged directly from a terminal after exporting the required variables. + +--- + +# 18. Sync Workflow + +The main synchronization entry point is: + +```text +scripts/sync.sh +``` + +It: + +1. Determines the builder root. +2. Locates the device configuration. +3. Checks for the A-Team setup marker. +4. Installs/runs the A-Team addon setup when necessary. +5. Determines the selected device synchronization script. +6. Changes to the selected ROM source. +7. Runs the device-specific synchronization script. + +The device setup marker is stored under the ROM tree: + +```text +device/A-Team/A-Team-Setup.check +``` + +When the marker exists, the main A-Team setup is skipped. + +This avoids repeatedly performing setup operations on the same ROM tree. + +--- + +# 19. MindTheGapps Synchronization + +The GApps script is: + +```text +scripts/gapps_sync.sh +``` + +The script selects the MindTheGapps branch from `ANDROID_VERSION`. + +The current mapping includes: + +```text +Android 16 -> baklava +Android 17 -> cinnamonbun +``` + +The destination is: + +```text +$ROM_PATH/vendor/gapps +``` + +The existing GApps source is removed before cloning the selected branch. + +Git LFS assets are then pulled. + +--- + +# 20. Build Options + +The GUI currently exposes several build-related selections. + +### Android Version + +Current GUI options include: + +```text +16 +17 +``` + +The selected value becomes: + +```text +ANDROID_VERSION +``` + +### Build Variant + +Current options include: + +```text +Userdebug +Eng +User +``` + +The internal project values are lowercase equivalents. + +### GApps Variant + +Current options include: + +```text +Vanilla +Gapps +Micro-G +Foss +``` + +### Clean Variant + +Current options include: + +```text +Full +Lite +None +``` + +### Installer Variant + +Current options include: + +```text +Custom A-Team ROM Installer +Default ROM Installer +``` + +### Build Jobs + +The Build Jobs control determines the parallel job count passed into the project. + +### Ccache + +The Ccache checkbox controls: + +```text +USE_CCACHE +``` + +### Custom APN + +The Custom APN checkbox controls: + +```text +APN_VARIANT +``` + +The current project environment represents enabled/disabled boolean selections using the values expected by the existing script layer. + +--- + +# 21. Project Profiles + +Project profiles are JSON files stored in: + +```text +profiles/ +``` + +A profile can preserve: + +```text +profile_name +host_name +device_name +rom_path +android_version +build_variant +build_command +gapps_variant +clean_variant +installer_variant +build_jobs +use_ccache +custom_apn +``` + +Profiles are useful for repeatedly building the same device/ROM combination. + +A profile does not replace the device or ROM configuration files. + +Instead, it stores the user's selected project state and the configuration system is still loaded when the project is used. + +--- + +# 22. Build Hosts + +Hosts are managed by: + +```text +builder/hosts_manager.py +``` + +Configuration: + +```text +configs/hosts.conf +``` + +The format is INI-style. + +Example: + +```ini +[Local] +type=local + +[BuildServer] +type=ssh +server_address=192.168.1.100 +port=22 +user=pizzag +remote_rom_source_path=/home/pizzag/Android +ssh_options= +``` + +The host manager builds SSH arguments using: + +```text +server_address +user +port +ssh_options +``` + +SSH options can contain an identity file and other supported SSH arguments. + +--- + +# 23. Remote Build Considerations + +Remote builds require more than simply having SSH available. + +The remote machine needs: + +- Android build dependencies +- Git +- Repo where required +- Git LFS where required +- ROM source at the expected location +- Device/vendor/kernel source as required by the ROM +- Any external tools required by the scripts + +The GUI is the management layer. + +It does not automatically install every Android build dependency on a remote machine. + +--- + +# 24. Terminal + +The Terminal tab creates a VTE terminal and starts: + +```text +/bin/bash +``` + +This is intentionally independent from the script runner. + +It gives the developer a direct shell for: + +```text +repo +git +lunch +m +brunch +adb +fastboot +grep +sed +python +bash +``` + +and other normal Android development operations. + +--- + +# 25. Resource Monitor + +The Resource Monitor launches: + +```text +btop +``` + +when available. + +If `btop` is unavailable, the script checks for: + +```text +bpytop +``` + +This is useful during large builds because Android compilation can heavily stress CPU, memory, storage, and other system resources. + +--- + +# 26. Tools Tab + +The Tools tab currently handles application-side utility functions. + +## Splash Screen + +The splash selector loads available splash assets and stores the selected splash. + +## Desktop Launcher Icon + +The icon selector loads available launcher icon choices. + +The selected icon is used when creating the application desktop launcher. + +## Desktop Launcher + +The launcher button invokes the launcher creation backend. + +## Clean ROM + +The clean button invokes the ROM cleaning action. + +The clean operation itself remains script/backend driven. + +--- + +# 27. UI Sizing Variables + +UI dimensions are deliberately exposed as constants near the top of `gui.py`. + +Current button width controls include: + +```text +SYNC_SETUP_BUTTON_WIDTH +SYNC_GAPPS_BUTTON_WIDTH +BUILD_ROM_BUTTON_WIDTH +LAUNCHER_BUTTON_WIDTH +CLEAN_BUTTON_WIDTH +``` + +This means button widths can be adjusted without hunting through individual GTK layout blocks. + +Other UI spacing controls include: + +```text +BUILD_SETUP_TOP_SPACING +PROJECT_PROFILES_TOP_SPACING +SYNC_SETUP_TOP_SPACING +``` + +These provide independent control over vertical spacing in the corresponding UI sections. + +This pattern should be followed when adding future UI dimensions. + +Instead of hard-coding: + +```python +button.set_size_request(140, -1) +``` + +prefer: + +```python +button.set_size_request( + BUILD_ROM_BUTTON_WIDTH, + -1 +) +``` + +This keeps layout tuning centralized. + +--- + +# 28. Updater Architecture + +Updater functionality is split between: + +```text +builder/updater.py +builder/updater_overlay.py +scripts/updater.sh +``` + +The shell updater emits machine-readable progress messages. + +For example: + +```text +::PROGRESS::1::5 +::STATUS::Downloading Update ... +``` + +The current updater stages are: + +```text +1/5 Downloading Update +2/5 Extracting Update +3/5 Backing Up Current Installation +4/5 Installing Update +5/5 Update Installed Successfully +``` + +The GTK overlay consumes these messages and advances its progress bar. + +This is preferable to guessing progress from arbitrary terminal output. + +--- + +# 29. Adding a New ROM + +A ROM does not normally require a new Python module. + +The typical process is: + +1. Create or sync the ROM source tree. +2. Select the ROM source directory in the GUI. +3. Add or select the appropriate ROM configuration. +4. Define required variables in `rom.conf`. +5. Add a build command entry if desired. +6. Ensure `scripts/build.sh` understands the resulting environment. +7. Add any ROM-specific sync/build scripts where needed. + +If the ROM should carry its own settings, place: + +```text +rom.conf +``` + +at the ROM root. + +This is especially useful when multiple ROM trees have different: + +- build commands +- manifest information +- branch naming +- vendor names +- output locations +- release naming +- version values + +--- + +# 30. Recommended Device Addition Workflow + +When adding a device, use this order: + +### Step 1 — Device config + +Create: + +```text +configs/devices/.conf +``` + +### Step 2 — Device identity + +Define: + +```text +DEVICE_CODENAME +DEVICE_DISPLAY_CODENAME +DEVICE_DISPLAY_NAME +DEVICE_MANUFACTURER +DEVICE_MODEL_NUMBER +``` + +### Step 3 — Device sync script + +Create: + +```text +scripts/devices_sync/-sync.sh +``` + +### Step 4 — Connect the two + +Set: + +```text +DEVICE_SYNC_SCRIPT="-sync.sh" +``` + +### Step 5 — Add device-specific variables + +Add only the values actually required by the device's scripts. + +### Step 6 — Test the sync script directly + +Before debugging the GUI, test the shell script with the required environment. + +### Step 7 — Launch the GUI + +The device should automatically appear in the device selector because discovery scans `configs/devices/*.conf`. + +--- + +# 31. Adding a New Build Command + +Edit: + +```text +configs/rom_build_commands.conf +``` + +Add a simple entry: + +```text +Lineage +``` + +or: + +```text +Derpfest +``` + +The current GUI turns normal entries into a lowercase command value. + +If a display-only/configuration entry is desired: + +```text +Default --> Rom.conf +``` + +can be used. + +After changing this file, restart the application so the Build tab reloads the list. + +--- + +# 32. Adding a New Build Variable + +If a script needs another value, first determine where the value belongs. + +### Device-specific + +Put it in: + +```text +configs/devices/.conf +``` + +### ROM-specific + +Put it in: + +```text +configs/rom.conf +``` + +or preferably the ROM-local: + +```text +/rom.conf +``` + +when the value belongs only to that ROM. + +### A-Team-wide setup + +Put it in: + +```text +configs/a_team_setup.conf +``` + +### Upload-specific + +Put it in: + +```text +configs/upload_services.conf +``` + +Then consume it from Bash: + +```bash +echo "$MY_VARIABLE" +``` + +Avoid modifying Python simply to introduce a variable that is naturally a configuration value. + +--- + +# 33. Debugging Configuration + +If a configuration value appears to be missing, check in this order: + +1. Is the file present? +2. Is the filename correct? +3. Is the filename case correct? +4. Does the line contain `=`? +5. Is the variable name spelled correctly? +6. Is the selected device correct? +7. Does the selected ROM contain its own `rom.conf`? +8. If it does, is that local file overriding `configs/rom.conf`? +9. Does the variable reference another variable that exists? +10. Does the script receive the environment being expected? + +The `Project.debug_dump()` helper can be useful when inspecting project state. + +--- + +# 34. Debugging the Script Layer + +Because the project is script-driven, a useful debugging technique is to run the underlying script manually. + +For example: + +```bash +cd /path/to/A-Team-Android_ROM_Builder +bash scripts/sync.sh +``` + +or: + +```bash +bash scripts/build.sh +``` + +with the required environment exported. + +This isolates Android build problems from GTK problems. + +If the script fails directly, changing the GUI usually will not fix the underlying ROM build problem. + +--- + +# 35. Debugging the GUI + +When modifying `gui.py`, test in layers. + +### Syntax + +```bash +python3 -m py_compile gui.py +``` + +### Startup + +```bash +python3 gui.py +``` + +### UI construction + +Verify that all tabs initialize: + +```text +Build Setup +Sync & Setup Device Source +Build +Terminal +Resource Monitor +Tools +``` + +### Action testing + +Exercise the changed button or dropdown rather than stopping after startup. + +This is particularly important for GTK code because a valid Python file can still fail during widget construction. + +--- + +# 36. Adding a New GUI Control + +The preferred pattern is: + +1. Add a constant near the other UI constants. +2. Create the widget. +3. Apply the constant. +4. Connect the signal. +5. Implement the callback. +6. Keep actual work in the backend/action/script layer. + +Example: + +```python +MY_BUTTON_WIDTH = 140 +``` + +Then: + +```python +self.my_button = Gtk.Button( + label="My Action" +) + +set_button_width( + self.my_button, + MY_BUTTON_WIDTH +) + +self.my_button.connect( + "clicked", + self.my_action_clicked +) +``` + +This is preferable to embedding a large shell workflow directly inside a GTK callback. + +--- + +# 37. Why Scripts Should Stay Separate + +Android ROM build operations frequently become device- and ROM-specific. + +Keeping the logic in: + +```text +scripts/ +``` + +allows: + +- shell testing without GTK +- easier debugging +- device-specific scripts +- ROM-specific behavior +- reuse outside the GUI +- simpler Python code +- easier migration between machines + +The GUI should primarily select and prepare the environment. + +--- + +# 38. Environment Flow Example + +Suppose the user selects: + +```text +Device: +Moto G Stylus 5G 2022 + +ROM: +Lineage + +Branch: +23.2 + +Android: +16 + +Build Variant: +Userdebug + +Jobs: +32 +``` + +The project state may become conceptually: + +```text +DEVICE_NAME=milanf +ROM_NAME=Lineage +ROM_BRANCH=23.2 +ANDROID_VERSION=16 +BUILD_VARIANT=userdebug +BUILD_JOBS=32 +``` + +The device configuration then adds values such as: + +```text +DEVICE_CODENAME=milanf +DEVICE_SOC=sm6375 +DEVICE_MANUFACTURER=Motorola +``` + +The ROM configuration adds values such as: + +```text +ROM_VENDOR_NAME=lineage +ROM_BRANCH_PREFIX=lineage- +ROM_MAJOR_VERSION=23 +ROM_MINOR_VERSION=2 +``` + +The final environment is what the scripts consume. + +--- + +# 39. Design Principles for Future Development + +When extending the project, prefer these rules: + +### Keep GUI and build logic separate + +Do not move large Bash workflows into GTK callbacks. + +### Prefer configuration over hard-coding + +If a value changes between devices or ROMs, it probably belongs in a config file. + +### Prefer device configs over device conditionals + +Prefer: + +```text +configs/devices/milanf.conf +``` + +over: + +```python +if device == "milanf": + ... +``` + +### Prefer ROM-local `rom.conf` for ROM-specific behavior + +This keeps a ROM's settings with its source tree. + +### Keep reusable UI dimensions centralized + +Add constants rather than hard-coding sizes in multiple places. + +### Test the actual UI + +Python syntax validation is not sufficient for GTK changes. + +### Test scripts independently + +A failing Android build script should be debugged as a script before changing GUI code. + +--- + +# 40. Common Failure Areas + +## Device does not appear + +Check: + +```text +configs/devices/ +``` + +and make sure the file ends in: + +```text +.conf +``` + +Also verify that it is not named one of the configuration files intentionally ignored by the device scanner. + +## ROM settings seem wrong + +Check whether: + +```text +/rom.conf +``` + +exists. + +If it does, it overrides: + +```text +configs/rom.conf +``` + +## Build command is missing + +Check: + +```text +configs/rom_build_commands.conf +``` + +and restart the application. + +## Device sync script is missing + +Check: + +```text +DEVICE_SYNC_SCRIPT +``` + +and verify: + +```text +scripts/devices_sync/