ADFA-4357 Add agent & contributor documentation set#1422
ADFA-4357 Add agent & contributor documentation set#1422hal-eisen-adfa wants to merge 12 commits into
Conversation
Add a coordinated set of Markdown docs to onboard both human and AI contributors and to capture the project's architectural decisions. - CLAUDE.md: operational guide for Claude Code (build/test commands, ABI flavors, project constraints); points to ARCHITECTURE.md for architecture rather than duplicating it. - AGENTS.md: operational rules for agents (CI-vs-local, Jira CLI, SonarQube MCP, git message handling); persistence rule now points to ARCHITECTURE.md. - ARCHITECTURE.md: single source of truth for module layout, layering & data flow (UDF), dependency rules, tech stack, state management, and the testing strategy. - REVIEW.md: code-review coaching (exception handling vs the Sentry crash wrapper, LeakCanary leaks, StrictMode, OWASP, tests/coverage, analytics, duplication, docstrings, strings.xml). - SECURITY.md: how to avoid introducing new SonarQube/Snyk/Semgrep blocker findings; vulnerability classes for an Android/Kotlin IDE. - docs/adr/: 8 Architecture Decision Records (MADR/Nygard) plus an index covering persistence-without-Room, on-device builds via the Gradle Tooling API, the vendored toolchain, embedded Termux, per-ABI flavors, Koin DI, the StrictMode whitelist engine, and retaining the com.itsaky.androidide namespace.
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: Organization UI Review profile: CHILL Plan: Pro Run ID: 📒 Files selected for processing (14)
✅ Files skipped from review due to trivial changes (10)
📝 WalkthroughA detailed high-level summary could not be generated for this review. Here is an overview derived from the analyzed file changes:
WalkthroughAdds a complete project documentation baseline: ChangesProject Documentation Suite
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~25 minutes Suggested reviewers
Poem
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
docs/adr/0005-per-abi-product-flavors.md (1)
39-39:⚠️ Potential issue | 🟡 Minor | ⚡ Quick winTrailing artifact at end of file.
Line 39 contains a stray
39character that appears to be a formatting artifact or incomplete truncation.Verify the file ends cleanly. If this is the intended end, remove the stray character.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@docs/adr/0005-per-abi-product-flavors.md` at line 39, The file docs/adr/0005-per-abi-product-flavors.md has a stray character "39" at the end that appears to be a formatting artifact. Locate the end of the file and remove this trailing character to ensure the markdown file ends cleanly without any extraneous content.
🧹 Nitpick comments (2)
REVIEW.md (1)
80-80: 💤 Low valueMinor: replace "exactly" with more specific verb.
LanguageTool flags "exactly" as an over-used intensifier. Consider "are" or "represent" depending on intended emphasis, or rephrase to avoid the intensifier.
Example:
-- **No duplication.** If you copy-pasted a block, extract a function/extension into the right `common`/`utils` module. Before adding a helper, grep — we likely already have it. Repeated literals/magic numbers → named constants. +- **No duplication.** If you copy-pasted a block, extract a function/extension into the right `common`/`utils` module. Before adding a helper, grep — we likely already have it. Repeated literals/magic numbers become named constants.Alternatively, keep the intensity but rephrase: "those are the error paths the crash wrapper would otherwise catch" → "those represent the error paths the crash wrapper would otherwise catch".
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@REVIEW.md` at line 80, In the REVIEW.md file, locate the sentence containing "those are exactly what the crash wrapper would otherwise catch in production" and remove the over-used intensifier "exactly" by replacing it with a more specific verb such as "represent" or rephrase the sentence to eliminate the intensifier entirely (for example, change "those are exactly what" to "those represent what" or similar phrasing that conveys the same meaning without the weak intensifier).docs/adr/0005-per-abi-product-flavors.md (1)
9-9: 💤 Low valueMinor: replace "very large" with a stronger adjective for clarity.
LanguageTool flags "very large" as an over-used intensifier. Consider "substantial", "sizable", or "prohibitive" depending on emphasis.
Example:
-Code On The Go is distributed primarily as a **direct APK download** from the App Dev for All website, not exclusively through Google Play, so we cannot rely on Play's automatic per-ABI splitting to slim downloads. +Code On The Go is distributed primarily as a **direct APK download** from the App Dev for All website, not exclusively through Google Play, so we cannot rely on Play's automatic per-ABI splitting to slim substantial downloads.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@docs/adr/0005-per-abi-product-flavors.md` at line 9, In the file docs/adr/0005-per-abi-product-flavors.md, replace the phrase "very large" with a stronger, more specific adjective in the sentence describing universal APK size. Consider using alternatives such as "substantial", "sizable", or "prohibitive" to provide clearer emphasis on why per-ABI splitting is necessary, as "very large" is flagged as an over-used intensifier. Choose the adjective that best conveys the intended severity of the size concern in the context of direct APK distribution.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Outside diff comments:
In `@docs/adr/0005-per-abi-product-flavors.md`:
- Line 39: The file docs/adr/0005-per-abi-product-flavors.md has a stray
character "39" at the end that appears to be a formatting artifact. Locate the
end of the file and remove this trailing character to ensure the markdown file
ends cleanly without any extraneous content.
---
Nitpick comments:
In `@docs/adr/0005-per-abi-product-flavors.md`:
- Line 9: In the file docs/adr/0005-per-abi-product-flavors.md, replace the
phrase "very large" with a stronger, more specific adjective in the sentence
describing universal APK size. Consider using alternatives such as
"substantial", "sizable", or "prohibitive" to provide clearer emphasis on why
per-ABI splitting is necessary, as "very large" is flagged as an over-used
intensifier. Choose the adjective that best conveys the intended severity of the
size concern in the context of direct APK distribution.
In `@REVIEW.md`:
- Line 80: In the REVIEW.md file, locate the sentence containing "those are
exactly what the crash wrapper would otherwise catch in production" and remove
the over-used intensifier "exactly" by replacing it with a more specific verb
such as "represent" or rephrase the sentence to eliminate the intensifier
entirely (for example, change "those are exactly what" to "those represent what"
or similar phrasing that conveys the same meaning without the weak intensifier).
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
Run ID: 636711f5-1206-408a-9727-feafce7276a9
📒 Files selected for processing (14)
AGENTS.mdARCHITECTURE.mdCLAUDE.mdREVIEW.mdSECURITY.mddocs/adr/0001-persistence-without-room.mddocs/adr/0002-on-device-builds-via-gradle-tooling-api.mddocs/adr/0003-vendored-forked-desktop-toolchain.mddocs/adr/0004-embedded-termux-runtime.mddocs/adr/0005-per-abi-product-flavors.mddocs/adr/0006-koin-dependency-injection.mddocs/adr/0007-strictmode-whitelist-engine.mddocs/adr/0008-retain-androidide-namespace.mddocs/adr/README.md
Promote accessibility from a proposed item to an enforced review section and add a parallel contextual-help (long-press 3-tier) rule, both keyed to existing patterns (ADFA-2667 screen-reader work, the idetooltips module). - REVIEW.md: new sections for content-description coverage and long-press help; matching 60-second-checklist entries; renumber trailing sections. - idetooltips/README.md: state the long-press-for-help-everywhere principle and the three-tier (tooltip / tooltip / web page) help model.
- ADR 0009: new IDE UI is Jetpack Compose, no new XML View screens; the UDF/Koin/StateFlow stack is unchanged. Indexed in docs/adr/README.md. - ARCHITECTURE.md: tech-stack UI row + overview now point to ADR 0009 instead of claiming the IDE is 'Not Compose'. - REVIEW.md: new Compose-only rule in Architecture alignment; accessibility (§8) now gives View + Compose forms for each rule (semantics, clearAndSetSemantics, the HardcodedText lint gap); contextual help (§9) notes idetooltips has no Compose entry point yet (displayTooltipOnLongPress is View-based); promote Offline-first from proposed to an accepted section.
…idge The Compose-only mandate (ADR 0009) and the long-press-everywhere rule (REVIEW.md section 9) need a Compose entry point into the View-based idetooltips system, which does not exist yet. Reference the follow-up ticket from both docs so the gap is tracked, not forgotten. Docs only.
…4382 The README's usage examples document a showIDETooltip() API that no longer exists (real API: TooltipManager.showTooltip / displayTooltipOnLongPress) and claim a Room store the module doesn't use (it's raw SQLite). Add a banner so contributors trust the code until the refresh lands. Docs only.
Leave idetooltips/README.md untouched on this PR. Removes both the design-principle section and the staleness banner added earlier; the README refresh is handled wholesale in ADFA-4382 instead.
- REVIEW.md: new Code-quality rule + 60-second-checklist entry requiring a change to update any module README/ARCHITECTURE.md/ADR it affects, or leave a tracked note. - AGENTS.md: one-line operational pointer to the REVIEW.md rule, so agents that read AGENTS.md (but not REVIEW.md) still apply it.
Tighten prose across CLAUDE.md, AGENTS.md, ARCHITECTURE.md, REVIEW.md, and the ADRs — cut hedging, doubled phrasings, and restated context; no facts, paths, commands, or decisions changed. Also: - REVIEW.md §9: drop the stale showIDETooltip reference in the intro. - ARCHITECTURE.md: reconcile the data-flow UI note with ADR 0009 (existing UI is Views; new UI is Compose) instead of a flat 'not Compose'.
- Experimental feature flag: clarify it's a user-facing early-access opt-in (singular flag), not a kill switch for us to disable features in the field. - Remove the performance-budget proposal; captured as ADFA-4383 instead.
Move it out of 'Open for discussion' into a numbered review section; gate not-yet-stable features behind the user-facing early-access flag. Renumber PR hygiene to §13.
…scussion section The MIN_SDK guard concern doesn't arise in practice; remove the item. It was the last proposal, so remove the empty section scaffolding too. REVIEW.md now ends at §13 PR hygiene.
| New persistence uses **raw SQLite** (`SQLiteOpenHelper` / `SQLiteDatabase`) or the **filesystem / preferences**. Room is **not** used for new code. | ||
|
|
||
| The one exception is the **Recent Projects** feature (`app/src/main/java/com/itsaky/androidide/roomData/recentproject/`, `@Database version = 4`), which predates this decision and is grandfathered in. Do not extend it with new entities or tables. (`idetooltips` still declares unused Room Gradle deps; its tooltip store is raw SQLite — remove those deps.) |
There was a problem hiding this comment.
Not true. AFAIK, raw SQLite is only used for indexing symbols from libraries (and the web server) because we want granular control over the index schema and queries, while also reducing the number of object allocations and overall memory use. Room should be preferred in most cases, but raw SQLite can be used for similar use cases.
There was a problem hiding this comment.
This could probably be removed if we add a statement somewhere that Room should be preferred, while raw SQLite should be used when the use case is justified (control over the actual schema, performance-critical code, etc.).
There was a problem hiding this comment.
This is almost entirely incorrect, but I do believe that we should have a document that distinguishes between the vendored toolchains, their use cases and how they differ from the tooling api toolchains.
- Modules in
composite-build/build-deps*are included in the final APK. They're part of the IDE's runtime and are used to provide certain features to the IDE. - They're kept in composite-builds to reduce build times - composite builds are a separate Gradle build from the main build, they're not built unless their sources are changed, even when we do a clean-build in the main build. Read more here: https://docs.gradle.org/current/userguide/composite_builds.html
- The toolchains in composite builds (
javac,jdk-compiler,jdk-jdeps,jdt, etc.) are used in the IDE's runtime. They're NOT used for providing ANY tooling API features, nor they're used to run the tooling API itself. For example, thejavac,jdk-compilercomposite builds and used to provide Java LSP features, like parsing and analyzing Java source files within the IDE's runtime - without having to invoke the JDK's javac viaProcessBuilder, or building our own custom parser/analyzer. - The tooling API is invoked using a full-blown JDK/JVM using
ProcessBuilderand runs as a daemon. The JDK used to run the tooling API and invoke Gradle builds is built from our appdevforall/terminal-packages repository and packaged within our terminal bootstrap packages. The IDE communicates with the tooling API (running as a daemon) using the JSONRpc protocol (the models/interfaces are defined insubprojects/tooling-api,subprojects/tooling-api-modelandsubprojects/tooling-api-eventsmodules).
|
|
||
| Code On The Go is the rebranded successor to **AndroidIDE**. The product name, branding, and assets changed, but the inherited codebase carries the original identity deeply: the application id and Gradle namespace are `com.itsaky.androidide` (`BuildConfig.PACKAGE_NAME`), `rootProject.name` is `AndroidIDE`, plus many thousands of references, the generated `R` class, the manifest, package-qualified vendored substitutions, signing identity, and existing installs in the field. | ||
|
|
||
| Changing an Android **application id** breaks the update path for installed users (a different app id is a different app) and disrupts signing/identity continuity. A rename of this size also ripples through the vendored `com.itsaky.androidide.build:*` substitutions ([ADR 0003](0003-vendored-forked-desktop-toolchain.md)). |
There was a problem hiding this comment.
Clarification worth adding: the major reason we have the package name set to com.itsaky.androidide is that it requires us to re-build terminal packages with the updated package name. Also, it is not possible to change package name incrementally (i.e. change in terminal packages first, then the app - or vice-versa). The change needs to be a big-bang change such that we have the package name changed in the terminal packages as well as this codebase (the application) as an atomic change.
| @@ -0,0 +1,37 @@ | |||
| Code On The Go is an Android IDE — it lets users edit, build, and deploy their own Android apps on-device, like Eclipse or VSCode. | |||
|
|
|||
| There is at least one Android emulator available. Find it with `adb devices -l | grep -v offline`, then use the `ANDROID_SERIAL` env var. | |||
There was a problem hiding this comment.
Not necessarily. x86_64 machines can't run the arm64/arm apps, sometimes not even with a translation layer. In that case, we might end up using physical devices instead (like I have to do right now, although I plan to work on getting the arm64 variant to work on devices with arm64 translation layer - like Waydroid).
|
|
||
| ## State Management | ||
|
|
||
| - **UI state is a single immutable `data class`** exposed as a `StateFlow<…UiState>`; the ViewModel mutates a private `MutableStateFlow` via `update { it.copy(...) }`. Derived booleans live as computed properties on the state class (so the UI stays dumb). |
There was a problem hiding this comment.
State should not necessarily be a data class, especially for UI that has multiple, mutually-exclusive states. It can lead to problems like "boolean hell" and state explosion. If a UI has multiple states (loading, installing, processing, completed, failed, cancelled, etc.) - they must almost always be represented with sealed classes. The goal of using sealed classes is to make the state machine explicit and ensure that incompatible states cannot co-exist at the same time.
| data class PluginManagerUiState( | ||
| val isLoading: Boolean = false, | ||
| val plugins: List<PluginInfo> = emptyList(), | ||
| val isPluginManagerAvailable: Boolean = false, | ||
| val isInstalling: Boolean = false, | ||
| ) { | ||
| val isEmpty: Boolean get() = plugins.isEmpty() && !isLoading // derived in state | ||
| val showEmptyState: Boolean get() = isEmpty && isPluginManagerAvailable | ||
| } |
There was a problem hiding this comment.
This is actually a good example of why it should use sealed classes: isLoading, isInstalling and isEmpty can be true at the same time.
The example should be changed to demonstrate mutually-exclusive state definition using sealed classes.
|
|
||
| ## Code style | ||
|
|
||
| 2-space indents everywhere. Java: Google style (`google-java-format`); Kotlin: `ktfmt` Google-internal style; XML: Android Studio formatter. Branch names must match `.../ADFA-#####` (3–5 digits) — see CONTRIBUTING.md; a pre-commit hook enforces it (`sh ./scripts/install-git-hooks.sh`). |
There was a problem hiding this comment.
Incorrect. Codebase is configured to use Spotless for formatting files. Spotless is configured to use tabs instead of spaces.
| ## How to use this | ||
|
|
||
| - **Author:** self-review against this list *before* requesting review. Most of it you can check in five minutes. | ||
| - **Reviewer:** you own correctness, leaks, security, and tests. Don't rubber-stamp; don't bikeshed style the formatter already enforces (`ktfmt` / `google-java-format`, 2-space indents). |
There was a problem hiding this comment.
Tabs as indents, not spaces.
| - [ ] **Tests:** non-UI logic has unit coverage. Where coverage is thin, there's logging to diagnose it in the field. | ||
| - [ ] **No duplication:** the change reuses existing helpers instead of copy-pasting. | ||
| - [ ] **Docs:** public classes/functions have KDoc/Javadoc explaining *why*, not *what*; any module `README`/`ARCHITECTURE.md`/ADR the change affects is updated in the same PR. | ||
| - [ ] **Strings** are in `strings.xml`, not inline literals. |
There was a problem hiding this comment.
Worth adding: strings should be added in the :resources module's strings.xml, not per-module. This is to ensure ease of translation.
ADFA-4357 — Agent & contributor documentation set
Adds a coordinated set of Markdown docs to onboard both human and AI contributors and to record the project's architectural decisions. Docs only — no code or build changes.
What's included
CLAUDE.mdARCHITECTURE.mdfor architecture.AGENTS.mdARCHITECTURE.mdREVIEW.mdstrings.xml.SECURITY.mddocs/adr/ADRs
com.itsaky.androididenamespace after rebrandNotes for reviewers
Content was written against the actual codebase (verified patterns: Koin DI, Firebase
IAnalyticsManager, the StrictMode whitelist engine, Sentry global handler,tooling-apiout-of-process, vendored toolchain). Two claims are author inferences worth a sanity check:ARCHITECTURE.md/SECURITY.md: "Retrofit is in the catalog but effectively unused in app code."Follow-ups (intentionally out of scope)
idetooltips(surfaced by ADR 0001/0003).ARCHITECTURE.mdtodocs/adr/.