More Expressive InstallerX !
# AGENTS.md
## Purpose
This file defines repository-specific instructions for coding agents working on **InstallerX Revived**.
Use it to decide:
* where a change belongs,
* which constraints must be preserved,
* what to verify before claiming a task is complete.
Task-specific maintainer instructions take precedence over this file. When the request is narrow, make the smallest coherent change that satisfies it.
For substantial features, invasive refactors, or behavior changes that span several files, sketch a short implementation plan before editing. Keep the plan aligned with the actual implementation as the work proceeds.
---
## Read these first when relevant
* `docs/README.md` β product scope, supported install flows, user-facing feature boundaries.
* `CONTRIBUTING.md` β translation policy, build prerequisites, contribution expectations.
* `.github/workflows/pr-check.yml` β the default CI build matrix used for pull requests.
* `settings.gradle.kts`, `app/build.gradle.kts`, and
`gradle/libs.versions.toml` β before touching Gradle, repositories, flavors, versions, or dependencies.
Do not duplicate or contradict those files casually. Update this file only for stable, repository-wide rules that agents should repeatedly follow.
---
## Repository overview
InstallerX Revived is a community-maintained Android installer with:
* dialog, notification, and automatic installation flows,
* support for APK, APKS, APKM, XAPK, APKs inside ZIP files, and batch APK installation,
* profile-driven install options and install flags,
* privileged workflows involving Root, Shizuku, Dhizuku, `app_process`, system package manager mode, and hidden APIs,
* switchable UI families based on Material 3 Expressive and Miuix.
Several product behaviors are intentionally flow-specific. Do **not** assume a feature supported in dialog installation is also valid for notification or automatic installation unless the existing code and docs already establish that.
---
## Critical project constraints
* Preserve the runtime network-access boundary. The unified APK may declare network permissions, but network requests must remain disabled when the in-app network setting is off.
* Prefer the repositoryβs existing **native API** paths and abstractions. Do not introduce shell-command implementations as a shortcut unless the maintainer explicitly requests it.
* Treat flow-specific behavior as flow-specific. A capability that exists for dialog installation is not automatically valid for notification or automatic installation.
* When changing behavior that is described in `docs/README.md`, update it or call out the documentation impact in the handoff.
---
## Project layout
### Top-level areas
* `app/` β main Android application.
* `app-process/` β privileged helper process bridge used by Root/Shizuku-style workflows.
* `hidden-api/` β hidden API declarations/helpers consumed by the app.
* `build-plugins/` β shared Gradle convention plugins.
* `baselineprofile/` β Android baseline profile generation.
* `docs/` β localized project README files and user-facing repository documentation.
* `.github/workflows/` β CI and release automation.
Do not assume every top-level directory is an included Gradle module. Confirm active modules in
`settings.gradle.kts` before making module-level assumptions.
### Main Kotlin package map
Under `app/src/main/java/com/rosan/installer/`:
* `core/` β shared low-level app infrastructure.
* `data/` β persistence, concrete providers, repositories, and mappers.
* `di/` β Koin modules and initialization wiring.
* `domain/` β domain models, repository contracts, providers, use cases, and business rules.
* `framework/` β Android/platform-facing integration code.
* `ui/` β screens, widgets, navigation, themes, and UI-specific models.
* `util/` β utility helpers.
Preserve this separation. Do not move behavior into a convenient but wrong layer just to finish faster.
---
## Build prerequisites
### Toolchain
* Use the repository Gradle Wrapper: `./gradlew ...`.
* The project requires **JDK 25**.
* Kotlin/JVM toolchains and Android compile settings are centrally defined; do not downgrade or loosen them unless the task explicitly requires it.
### GitHub Packages authentication
The project resolves snapshot `miuix` artifacts from GitHub Packages.
For local builds, credentials are expected outside the repository, typically in the global Gradle properties file:
```properties
gpr.user=YOUR_GITHUB_USERNAME
gpr.key=YOUR_PERSONAL_ACCESS_TOKEN
```
The token needs `read:packages` access. CI may instead use `GITHUB_ACTOR` and `GITHUB_TOKEN`.
Never commit credentials, inline them into tracked files, or weaken the existing credential handling.
---
## Default verification
### Standard smoke build
For changes that do not affect variant-specific behavior, prefer the faster single-variant smoke build:
```bash
./gradlew assembleUnstableDebug
```
Use the PR-equivalent build when the change can reasonably affect app compilation, resources, dependency wiring, or variant-sensitive behavior:
```bash
./gradlew assemblePreviewDebug
```
For local agent-run verification, do not pass a custom `APP_ID` unless the maintainer explicitly asks for an alternate application ID.
### Report verification honestly
When summarizing work:
* state which commands were run,
* state whether they passed,
* say explicitly when verification was not run or could not be completed.
Do not imply a build or test passed unless it actually did.
---
## Gradle, variants, and dependency rules
### Flavors and build levels
The app currently uses one flavor dimension:
* level:
* `Unstable`
* `Preview`
* `Stable`
Important build behavior includes:
* build-level-specific `BUILD_LEVEL`,
* git-hash version suffixes for unstable/preview outputs,
* an optional `VERSION_NAME` Gradle override for release automation.
Do not flatten, rename, or silently bypass flavor logic. If behavior differs by variant, make that relationship explicit.
### Dependencies
* Prefer `gradle/libs.versions.toml` for dependency and plugin version changes.
* Follow the existing version catalog naming style.
* Do not scatter raw dependency coordinates or versions across module build files without a strong reason.
* Respect the current centralized repository setup and `RepositoriesMode.FAIL_ON_PROJECT_REPOS`.
* The GitHub Packages `miuix` repository is intentionally configured in `settings.gradle.kts`; do not duplicate it in subprojects.
### Signing and release flow
* Release and debug signing behavior is handled centrally in `app/build.gradle.kts`.
* Local builds may fall back to the debug keystore when custom signing material is absent.
* Stable release packaging is automated in `.github/workflows/manual-stable-release.yml`.
Do not alter signing fallback, artifact naming, release workflow commands, version generation, or stable-release logic unless the maintainer explicitly asks for that.
---
## Architecture conventions
### Dependency injection
Use the existing Koin structure in `app/src/main/java/com/rosan/installer/di/`.
Relevant modules already include areas such as:
* core,
* device,
* engine,
* initialization,
* installer sessions,
* privileged behavior,
* serialization,
* settings,
* view models.
When introducing a new injectable dependency:
* place it in the most relevant existing module,
* avoid ad-hoc global singletons,
* keep initialization wiring explicit.
### Application initialization
`App.kt` performs important global startup work, including:
* crash handling initialization,
* hidden API exemptions on supported Android versions,
* Monet setup for older platform versions,
* conditional logging setup,
* Koin bootstrap,
Treat the order and presence of this startup logic as sensitive. Do not reorder or remove initialization steps unless the task requires it and the consequences are understood.
### Domain and data boundaries
Keep business rules and platform/data access separate:
* domain models and use cases should not become Android UI utilities,
* data repositories/providers should not grow presentation logic,
* UI code should not bypass established repository/use-case boundaries when a domain path already exists.
Prefer extending the existing pattern used by the nearest comparable feature.
---
## Settings-related changes
Settings in this repository are layered and should stay that way.
### Typical settings layout
Domain side:
* `domain/settings/model/`
* `domain/settings/provider/`
* `domain/settings/repository/`
* `domain/settings/usecase/`
* `domain/settings/util/`
Data side:
* `data/settings/local/`
* `data/settings/mapper/`
* `data/settings/provider/`
* `data/settings/repository/`
### Checklist for adding or changing a setting
When a setting is persisted or exposed through app state, verify whether the change needs:
1. a domain model or state update,
2. provider/repository contract changes,
3. data-layer storage or mapping updates,
4. DI wiring updates,
5. UI state/action/view-model changes where that feature is presented,
6. both Material 3 and Miuix screen updates when both UI families expose the same setting,
7. English and Simplified Chinese string updates.
Do not implement only the visible switch while leaving persistence, mapping, or downstream behavior inconsistent.
---
## UI conventions
### Material 3 Expressive and Miuix are separate UI families
The repository keeps page implementations under distinct paths such as:
* `ui/page/main/`
* `ui/page/miuix/`
Respect that split.
Do not:
* leak Miuix-only components into Material 3 screens without intent,
* rebuild Material 3 screens with Miuix assumptions,
* change shared logic while checking only one UI family.
When a feature exists in both design systems, preserve semantic consistency while allowing implementation details to remain native to each UI family.
### Reusable UI components
For common widgets and shared components:
* keep dependencies as narrow as the existing component boundary allows,
* do not hardcode behavior that should be supplied by the caller,
* avoid locking reusable components to one screen-specific style or workflow,
* prefer composable APIs that remain extensible rather than baking product decisions into generic widgets.
Follow nearby component patterns before inventing a new style.
---
## Text, translation, and wording
### Translation policy
Per repository contribution policy:
* English and Simplified Chinese strings are maintained by developers.
* Other languages should go through Weblate rather than direct translation PRs.
### When changing user-visible strings
* Update English and Simplified Chinese together when the changed text belongs to both maintained locales.
* Preserve established product terminology unless the task is explicitly a wording cleanup.
* Keep safety caveats and compatibility warnings precise. Do not soften them just to make copy shorter.
* When text distinguishes concepts such as global authorization, profile authorization, install initiator, requester, or system limitations, keep those distinctions intact.
---
## Privileged and installation behavior
This codebase interacts with highly sensitive platform behavior, including:
* app installation flows,
* install flags and profile inheritance,
* user/all-user installation handling,
* Root, Shizuku, Dhizuku, and hidden API paths,
* ROM-specific compatibility workarounds,
* attempts to bypass OEM interception only where the project already supports that behavior.
### Rules for sensitive changes
Before changing privileged or install behavior:
1. identify the exact flow being modified: dialog, notification, automatic, profile, or system integration,
2. check whether the feature is already documented as flow-specific,
3. preserve permission boundaries and do not imply capabilities the current authorizer cannot provide,
4. avoid widening behavior from one privileged backend to another without explicit evidence,
5. keep ROM compatibility behavior explicit instead of hiding it behind vague generic logic.
If a change affects data safety, install success, system-API fallbacks, or ROM-specific behavior, explain the tradeoff clearly in the final summary.
---
## Source and API discipline
* Prefer native APIs and the repositoryβs existing abstractions over ad-hoc shell-command workflows.
* Reuse existing platform wrappers, providers, and repositories before adding parallel paths.
* Avoid introducing reflection, hidden API access, or privileged shortcuts where an existing maintained path already exists.
* When adding compatibility logic, keep version checks and backend checks local and readable.
---
## CI and workflow boundaries
The workflow directory contains purpose-specific automation such as:
* pull request build checks,
* preview/dev automation,
* release automation,
* CodeQL or other maintenance workflows.
When editing workflows:
* change only the workflow relevant to the request,
* preserve least-privilege token permissions unless explicitly required,
* keep package-auth requirements intact,
* do not conflate PR validation with release packaging.
Release automation deserves extra caution because it may involve version inputs, signing material, artifact renaming, and draft release creation.
---
## Recommended agent workflow
For implementation tasks, follow this order:
1. Restate the concrete behavior being changed.
2. Locate the smallest relevant area of the repository.
3. Find the nearest existing pattern and extend it.
4. Update all affected layers, not only the most visible file.
5. Run the narrowest meaningful verification, defaulting to the CI-equivalent smoke build when compilation impact is plausible.
6. Summarize:
* what changed,
* why this shape was chosen,
* what was verified,
* what remains unverified.
Prefer targeted, reviewable edits over sweeping refactors.
---
## Commit message and submission discipline
Do not create commits, push branches, or open pull requests unless the maintainer explicitly asks for that.
Before preparing a commit message:
* inspect `git status` and the relevant diff,
* decide whether the change is one coherent change or multiple independent changes,
* include only files related to the requested task,
* do not include user-owned unrelated changes, generated artifacts, credentials, local IDE files, or build outputs.
Write commit messages in the repository's Conventional Commits style.
Subject format is mandatory:
```text
type: short lowercase description
type(scope): short lowercase description
```
Use only these top-level types unless the maintainer explicitly asks for another one:
* `fix:` β bug fixes, behavior corrections, compatibility fixes, UI defects, build fixes.
* `feat:` β new user-facing or maintainer-facing capabilities.
* `refactor:` β code restructuring without intended behavior changes.
* `docs:` β documentation-only changes.
* `i18n:` β translation-only updates, especially Weblate-style changes.
* `fix(deps):` β dependency update commits.
Subject rules:
* keep the subject at or below 72 characters,
* use lowercase after the type prefix unless naming a proper noun, API, class, or UI brand,
* use imperative mood after the prefix,
* describe behavior or developer intent rather than listing files,
* include a concise body for most non-trivial commits, especially when the change has multiple behavior points, important intent, or risk,
* use a one-line message only for trivial, self-evident changes,
* use bullets only for genuinely separate changes, risks, or dependency groups,
* avoid generic wording such as "Refined", "Enhanced", "Improved", or "Updated",
* do not invent issue numbers, user impact, names, emails, or identifiers,
* do not add AI signatures, `Co-authored-by`, or generated-by trailers unless explicitly requested.
Examples that match repository style:
* `fix: restore config scopes on undo`
* `fix: fix Miuix sheet dismissal behavior`
* `feat: add smart authorizer fallback settings`
* `refactor: define explicit parameters for ShizukuUserServiceRecycler`
* `docs: document agent submission and repo layout`
For dependency changes:
* explicitly list package, library, plugin, or tool names,
* include version changes in `from -> to` form when available,
* mention scope when inferable, such as runtime, build plugin, Gradle, Maven, npm, or pnpm,
* if the change is primarily dependency updates, start the subject with `fix(deps):`,
* do not collapse unrelated dependency updates into vague wording like "update dependencies" or "bump deps".
If verification was not run or did not pass, do not write the commit or handoff as though it was verified.
---
## Common mistakes to avoid
* Editing one UI family and forgetting the parallel Material 3 or Miuix surface.
* Adding a setting toggle without updating persistence or state propagation.
* Adding repositories to module Gradle files despite centralized repository management.
* Hardcoding dependency versions outside the version catalog.
* Modifying release/signing/version automation during unrelated work.
* Treating dialog-only install behavior as universally available.
* Weakening or deleting compatibility warnings from strings without understanding why they exist.
* Reordering app initialization code as a βcleanup.β
* Claiming a build passed when no verification was run.
---
## Maintainer-facing handoff format
When finishing a task, give a compact handoff that includes:
* **Changed:** files or areas updated.
* **Behavior:** what users or maintainers should expect now.
* **Verification:** commands run and result.
* **Notes:** migration concerns, unverified scenarios, or follow-up risks only when genuinely relevant.
Keep the report factual and specific.