Skip to content

ADFA-4357 Add agent & contributor documentation set#1422

Open
hal-eisen-adfa wants to merge 14 commits into
stagefrom
ADFA-4357-add-markdown-files-for-agents
Open

ADFA-4357 Add agent & contributor documentation set#1422
hal-eisen-adfa wants to merge 14 commits into
stagefrom
ADFA-4357-add-markdown-files-for-agents

Conversation

@hal-eisen-adfa

Copy link
Copy Markdown
Collaborator

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

File Purpose
CLAUDE.md Operational guide for Claude Code: build/test commands, ABI flavors, project constraints. Points to ARCHITECTURE.md for architecture.
AGENTS.md Operational rules for agents: CI-vs-local, Jira CLI, SonarQube MCP, git-message handling.
ARCHITECTURE.md Single source of truth for module layout, layering & data flow (UDF), dependency rules, tech stack, state management, testing.
REVIEW.md Code-review coaching: exception handling (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) + index.

ADRs

  1. Persistence without Room
  2. On-device builds via the Gradle Tooling API (out-of-process)
  3. Vendored/forked desktop toolchain via composite-build substitution
  4. Embedded Termux runtime
  5. Per-ABI product flavors (v7/v8)
  6. Koin for dependency injection
  7. Custom StrictMode whitelist engine
  8. Retaining the com.itsaky.androidide namespace after rebrand

Notes for reviewers

Content was written against the actual codebase (verified patterns: Koin DI, Firebase IAnalyticsManager, the StrictMode whitelist engine, Sentry global handler, tooling-api out-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."
  • ADR 0005: the per-ABI rationale assumes direct-APK-download is the primary distribution channel (Play App Bundle splits treated as not relied upon).

Follow-ups (intentionally out of scope)

  • Remove the unused Room Gradle deps in idetooltips (surfaced by ADR 0001/0003).
  • Optional: add a back-link from ARCHITECTURE.md to docs/adr/.

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.
@coderabbitai

coderabbitai Bot commented Jun 18, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 69307dbc-5408-446e-a1f0-352bb15ec8b8

📥 Commits

Reviewing files that changed from the base of the PR and between 27ef16b and b8396cc.

📒 Files selected for processing (1)
  • REVIEW.md
✅ Files skipped from review due to trivial changes (1)
  • REVIEW.md

📝 Walkthrough
  • Added repo operational documentation: CLAUDE.md (Claude Code usage/build-test commands, ABI flavor conventions, repo constraints) and AGENTS.md (agent execution/CI rules, Jira CLI usage, SonarQube MCP behavior, and safe multi-line git/gh messaging).
  • Established the architecture “single source of truth” in ARCHITECTURE.md (module/subsystem layout, UDF + Koin/Flow state model, persistence/dependency rules, and testing guidance).
  • Added contributor/PR review standards in REVIEW.md (exception handling, LeakCanary/StrictMode expectations, OWASP/security checks, testing/coverage expectations, analytics/logging rules, and accessibility/UI help conventions).
  • Added SECURITY.md (baseline to avoid new SonarQube/Snyk/Semgrep blockers, Kotlin/Android vulnerability-class checklist, and private vulnerability reporting).
  • Added 9 Architecture Decision Records under docs/adr/ plus an ADR index:
    • Persistence without Room (Room only for “Recent Projects”)
    • On-device builds via Gradle Tooling API (out-of-process)
    • Vendored/forked desktop toolchain substitution for build dependencies
    • Embedded Termux runtime
    • Per-ABI product flavors (v7/v8) and flavor-qualified build tasks/asset bundling
    • Koin dependency injection (vs Hilt/Dagger)
    • Custom StrictMode whitelist engine
    • Retain com.itsaky.androidide namespace (presentation-layer rename only)
    • Require Jetpack Compose for new UI
  • Risks / best-practice considerations:
    • Docs-only change, but the main risk is guidance drift or mismatch with implementation—ensure these conventions stay aligned with CI/tooling outputs over time.
    • Review the two embedded assumptions to confirm they remain true: Retrofit effectively unused in app code, and per-ABI rationale assuming direct APK downloads as the primary distribution channel.

Walkthrough

Adds repository-wide documentation for operating rules, architecture conventions, review standards, security guidance, and ADRs covering persistence, build, runtime, DI, flavors, StrictMode, namespace retention, and Compose.

Changes

Project Documentation Suite

Layer / File(s) Summary
AI agent and contributor operating guides
AGENTS.md, CLAUDE.md
Defines emulator selection, persistence limits, dependency and sizing rules, CI/Jira/SonarQube conventions, tempfile-based git/gh messaging, flox-wrapped Gradle usage, ABI flavor task naming, and document references.
Architecture overview and implementation rules
ARCHITECTURE.md
Defines the on-device IDE layering, module boundaries, dependency direction, flavor/build conventions, persistence policy, state-management patterns, and testing guidance.
Architecture Decision Records and ADR index
docs/adr/README.md, docs/adr/000*
Adds the ADR index and records decisions for persistence without Room, Gradle Tooling API builds, vendored toolchains, embedded Termux, per-ABI flavors, Koin DI, StrictMode whitelist enforcement, namespace retention, and Jetpack Compose for new UI.
Code review rules and workflow checks
REVIEW.md
Adds review checklists and rules for exceptions, leaks, StrictMode, security, tests, observability, accessibility, contextual help, offline-first behavior, feature gating, plugin impact, and PR hygiene.
Security baseline and vulnerability guidance
SECURITY.md
Defines the blocker baseline policy, tool responsibilities, vulnerability classes to avoid, dependency and reliability guidance, and pre-push/private reporting instructions.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Suggested reviewers

  • jatezzz
  • itsaky-adfa
  • jomen-adfa

Poem

🐇 I nibbled through docs, crisp and neat,
ADRs lined up in a tidy seat.
AGENTS, REVIEW, and SECURITY too,
A rabbit hops where the rules shine through.
Compose and architecture, side by side—
Hoppy trails for this codebase ride! 🥕

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly summarizes the docs-only change by naming the new agent and contributor documentation set.
Description check ✅ Passed The description is directly aligned with the change set and accurately summarizes the added documentation and ADRs.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch ADFA-4357-add-markdown-files-for-agents

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.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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 win

Trailing artifact at end of file.

Line 39 contains a stray 39 character 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 value

Minor: 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 value

Minor: 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

📥 Commits

Reviewing files that changed from the base of the PR and between 8082c92 and d279292.

📒 Files selected for processing (14)
  • AGENTS.md
  • ARCHITECTURE.md
  • CLAUDE.md
  • REVIEW.md
  • SECURITY.md
  • docs/adr/0001-persistence-without-room.md
  • docs/adr/0002-on-device-builds-via-gradle-tooling-api.md
  • docs/adr/0003-vendored-forked-desktop-toolchain.md
  • docs/adr/0004-embedded-termux-runtime.md
  • docs/adr/0005-per-abi-product-flavors.md
  • docs/adr/0006-koin-dependency-injection.md
  • docs/adr/0007-strictmode-whitelist-engine.md
  • docs/adr/0008-retain-androidide-namespace.md
  • docs/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.
@hal-eisen-adfa hal-eisen-adfa marked this pull request as draft June 19, 2026 03:37
- 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.
@hal-eisen-adfa hal-eisen-adfa marked this pull request as ready for review June 19, 2026 06:57
Comment on lines +15 to +17
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.)

@itsaky-adfa itsaky-adfa Jun 23, 2026

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.).

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

  1. 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.
  2. 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
  3. 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, the javac, jdk-compiler composite 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 via ProcessBuilder, or building our own custom parser/analyzer.
  4. The tooling API is invoked using a full-blown JDK/JVM using ProcessBuilder and 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 in subprojects/tooling-api, subprojects/tooling-api-model and subprojects/tooling-api-events modules).


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)).

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Comment thread AGENTS.md
@@ -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.

@itsaky-adfa itsaky-adfa Jun 23, 2026

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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).

Comment thread ARCHITECTURE.md

## 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).

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Comment thread ARCHITECTURE.md
Comment on lines +117 to +125
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
}

@itsaky-adfa itsaky-adfa Jun 23, 2026

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Comment thread CLAUDE.md

## 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`).

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Incorrect. Codebase is configured to use Spotless for formatting files. Spotless is configured to use tabs instead of spaces.

Comment thread REVIEW.md
## 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).

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Tabs as indents, not spaces.

Comment thread REVIEW.md
- [ ] **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.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Worth adding: strings should be added in the :resources module's strings.xml, not per-module. This is to ensure ease of translation.

Comment thread AGENTS.md
@@ -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.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's merge the contents of AGENTS.md directly into CLAUDE.md. Claude Code automatically reads CLAUDE.md on initialization. If we force it to perform a secondary tool call to read AGENTS.md, we waste context window tokens, slow down startup, and risk the agent ignoring crucial operational rules if the file read fails.

Comment on lines +3 to +11
- **Status:** Accepted
- **Date:** 2026-06-19
- **Deciders:** Code On The Go team

## Context

Historically the IDE's own UI is **View-based** — XML layouts, `Fragment`s, and `RecyclerView` with Material Components (see [ADR 0006](0006-koin-dependency-injection.md) context and ARCHITECTURE.md). Newer surfaces already moved to a Unidirectional Data Flow (UDF) architecture — `ViewModel` + `StateFlow`, sealed UI-state/effect types, repositories, Koin DI — but still render through XML and `findViewById`/binding.

That split has a cost: two ways to build a screen, manual view-state wiring, boilerplate binding code, and UI logic that's awkward to unit-test. Jetpack Compose collapses the view layer into Kotlin, binds naturally to `StateFlow` via `collectAsState()`, and fits the UDF pattern the team already follows. Unlike most ADRs here, this one is **forward-looking** — it sets direction for new work rather than documenting an existing decision.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should have a plugin-api.md file as well, stating best practices like ensuring any changes to the API does not break binary compatibility

Comment thread AGENTS.md

Avoid adding dependencies — we almost certainly already have what you need. Check `build.gradle.kts`.

Plan before building, and size the change (files + LOC). If it will exceed 500 LOC or 10 files, split it into 2+ change sets so the user can land them as separate PRs.

@fryanpan fryanpan Jun 30, 2026

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This feels prescriptive and has some negative consequences.

There's overhead from splitting code up. Especially if a future change requires making edits that go across the PRs.

Where we landed at Deepcell was to usually go with one PR per ticket/use case. But try to break the PR up into reviewable commits. Plus separate mechanical changes in different commits from more complex changes that needed more human review. Then ask teammates to review by commit.

Over time, with LLM assistance, people can handle bigger PRs.

Comment thread REVIEW.md
- **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).
- Tie every blocking comment to a concrete risk (a crash, a leak, a CVE class, an untested branch). Tag non-blocking polish as **nit:** so the author can triage.

## The 60-second checklist

@fryanpan fryanpan Jun 30, 2026

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Curious how well this works to catch most of the most important areas a review should catch.

In the REVIEW.md docs there's an explicit note saying that Claude does not look up file references or imports in the REVIEW.md, which might be a bit limiting.

e.g. the ADRs and ARCHITECTURE.md docs are mostly not represented directly in this file and might be missed

As an alternative, having a skill that activates on each code review would allow claude (or subagents) to read other files as guidance.

Could be helpful to ask Claude to run a code review pass on several PRs using what's here. See if it does properly review for architecture or not.

And compare that with a skill that explicitly does an architecture review by reviewing against guidance in ARCHITECTURE.md

Comment thread REVIEW.md
@@ -0,0 +1,174 @@
# Code Review Guide

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

One question I have while reading this -- as a first step, hopefully this helps Claude review the right things.

But then, how does Claude prove it reviewed correctly?

So I think it's worth trying this REVIEW.md as is -- see if it 1) does review all the things you hope it'll review and 2) convinces you it did review thoroughly.

A suggestion for how to address this is here

You can bake it into the REVIEW.md or an associated skill to tell Claude to make sure it did review each item. And then show you proof of what it did.

But that may be overkill if this REVIEW.md already works!

Comment thread REVIEW.md

The app runs a real StrictMode policy via `StrictModeManager` with a **whitelist engine**. Project rule (see learnings/memory): **the whitelist is only for vendor/framework code we can't change — never for app-owned violations.** If your code trips StrictMode, fix the code.

- Move disk and network I/O off the main thread (`Dispatchers.IO`, `withContext`). No DB reads, file reads, or `SharedPreferences` first-access on the UI thread.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also maybe any long-running compute (like decoding a large file, etc.) should be off main thread. There was a recent Sentry bug where JSON decoding on main thread caused crashes.

Comment thread REVIEW.md
@@ -0,0 +1,174 @@
# Code Review Guide

How to give a good review on Code On The Go. This is a coaching doc, not a gate — use judgment, explain the *why*, and prefer a concrete suggestion (or a diff) over "this is wrong." It complements, and does not replace, [ARCHITECTURE.md](ARCHITECTURE.md) (the source of truth for patterns) and the operational rules in `AGENTS.md` / `CLAUDE.md`.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Judgement and context are important; however, if there are verifiable things the team almost always cares about, then the earlier Claude catches these "gates" the better.

And if you give Claude a clear way to test the gate, it'll do so more often.

Will add a few comments below to suggest where more verifiable gates might be worth considering.

Comment thread REVIEW.md

## 5. Tests & coverage

**If the code is not purely UI, expect unit tests in the same PR.** ViewModels, repositories, parsers, builder/tooling logic, and security-sensitive helpers are all testable off-device.

@fryanpan fryanpan Jun 30, 2026

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This section may benefit from a more verifiable target -- but still leave room for judgement.

e.g. On recent ADFA work, I've asked Claude to aim for 90% line & branch coverage on all new, non-UI code. And asked it to prove it using code coverage results.

Not sure if this matches what the team cares about though -- is there a more specific target that describes what the team cares about?

Comment thread REVIEW.md

## 7. Code quality

- **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.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is one form of duplication issue. But there are others. I've had some success asking Claude to do a pass to check for loose coupling and good cohesion.

Look for where there might be duplicated logic or behaviour across files. This kind of duplicated logic might come from copy and paste. But it might also come from Claude reimplementing something that's already implemented. Or reimplementing the same thing more than once in different places while building out a feature. Especially when work starts getting split up into chunks by subagent.

Comment thread REVIEW.md
- **Persistence:** raw SQLite or filesystem — **not Room** (Recent Projects is the lone legacy exception).
- **UI safety:** never place our UI over the two Android system bars — the top status bar and the bottom navigation bar (`AGENTS.md`).

## 11. Offline-first

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How do you want Claude to verify this and prove it works?

(On tickets I was working on I planned out tests with Claude on which parts of the workflow needed to work offline and then had test cases for it -- had Claude use adb over USB and explicitly turn off the Wifi network for tests)

Comment thread REVIEW.md

## 10. Architecture alignment

Hold the change to the patterns in [ARCHITECTURE.md](ARCHITECTURE.md):

@fryanpan fryanpan Jun 30, 2026

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Mentioned above -- docs suggest Claude might not follow file links in the REVIEW.md?

If this is the case, then could be helpful to bring over a short checklist of the most critical architecture items into this doc.

Does the list below cover the most important things?

Comment thread REVIEW.md

## 2. Memory & resource leaks — fix them before LeakCanary does

LeakCanary runs in debug builds (`debugImplementation`), so leaks *will* surface — catch them in review first. Common offenders here:

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Below look like good guidelines. Is there a way to check this more explicitly during testing?

e.g. if E2E + unit tests triggered any leaks during automated testing, is there a way to see if LeakCanary flagged anything?

@fryanpan

fryanpan commented Jun 30, 2026

Copy link
Copy Markdown
Contributor

Feature completeness
One general comment -- reviewed the Claude system prompt and in code review sections, the system prompt does not cover whether the PR actually does what the ticket asks for.

So could be useful to have Claude look up the Jira ticket to see if the plan covers requirements, whether testing covers the intended flow, and also review to see if all requirements are implemented.

One other random thought -- it came up in one of the meetings I was in that the team wished for more updates while work is in progress in the ticket. That's another brief rule you could add to this PR.

@fryanpan

Copy link
Copy Markdown
Contributor

Had an hour on the train up from LA to take a look. Looks like a great foundation!

Added a few comments.

@fryanpan

Copy link
Copy Markdown
Contributor

Follow up question is how do we tell if this PR is good?

What testing have we done? Or do we plan to do?

e.g. Has this harness been used to implement a ticket?

e.g. Should the issues in the code review conventions mostly get caught by Claude before opening a PR going forward? Might be useful to audit PR feedback after this harness is in place to see what it regularly misses.

Comment thread SECURITY.md

---

## What the three tools catch (and where they differ)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does this PR also depend on Claude's built in /security-review skill?

https://support.claude.com/en/articles/11932705-automated-security-reviews-in-claude-code

Over time, I suspect that may prove to be more powerful (and likely already is) than other tools since it's such a generally useful engineering need.

Comment thread REVIEW.md
Comment thread REVIEW.md

## 13. Consider impact on plugins

Plugins might conflict with each other. New core features might cause plugins to break even if they don't change the plugin API. The review process must consider the impact of the current change on plugins in the wild.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This feels a little vague -- when I dropped by the office one Tuesday, I think Hal mentioned that we don't want to freeze the plugin API yet, or even guarantee backward compatibility. Since it's still early and we care more about evolve as we discover what plugins need.

But maybe we may still want to check for breaking API changes and make sure they happen deliberately (documented and justified)?

Also, how does one "consider the impact of a change on plugins in the wild"? Perhaps people familiar with the plugins and CodeOnTheGo can do this. I'm not sure I can. And I'm not sure this is specific enough for Claude to do -- and maybe that's okay.

One mechanical thing I think Claude could help with though is if there's a significant or breaking change, ask it to review at least the plugin-examples repo to see what the impact is on the growing family of example plugins.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants