From e81325ccf70e9c8938509bce14de78fd0cecf6e7 Mon Sep 17 00:00:00 2001 From: Petros Paraskevopoulos Date: Wed, 4 Mar 2026 12:26:14 +0200 Subject: [PATCH 1/6] AI: Add claude.md with project guidance for coding agents Add CLAUDE.md at the repository root, auto-generated via the `/init` command, documenting project overview, build commands, architecture, testing conventions, important gotchas, and publishing details to help coding agents operate effectively in this codebase. Co-Authored-By: Claude Opus 4.6 --- CLAUDE.md | 67 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 67 insertions(+) create mode 100644 CLAUDE.md diff --git a/CLAUDE.md b/CLAUDE.md new file mode 100644 index 0000000..c225afb --- /dev/null +++ b/CLAUDE.md @@ -0,0 +1,67 @@ +# CLAUDE.md + +This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository. + +## Project Overview + +Android client library for tracking user events (Nosara/Tracks), A/B testing (ExPlat), and crash logging (Sentry). Published to Automattic's S3 Maven repository. Used internally by Automattic mobile apps. + +## Build Commands + +```bash +./gradlew assembleDebug # Build all modules +./gradlew testDebugUnitTest # Run all unit tests +./gradlew lintDebug # Run lint checks +./gradlew ciktlint # Run ktlint checks +./gradlew buildHealth # Dependency analysis +./gradlew :experimentation:apiCheck # Binary compatibility check (experimentation only) +``` + +To run a single test class: + +```bash +./gradlew :experimentation:testDebugUnitTest --tests "com.automattic.android.experimentation.ExPlatTest" +./gradlew :crashlogging:testDebugUnitTest --tests "com.automattic.android.tracks.crashlogging.SentryCrashLoggingTest" +``` + +**Note:** `gradle.properties` is gitignored. CI copies `gradle.properties-example` before building. Locally, copy it manually if needed: `cp gradle.properties-example gradle.properties`. + +## Architecture + +Three independently published library modules plus a sample app and benchmark module: + +| Module | Artifact | Language | Description | +|--------|----------|----------|-------------| +| `AutomatticTracks` | `com.automattic:Automattic-Tracks-Android` | Java + Kotlin | Core event tracking with SQLite storage and background network transmission | +| `experimentation` | `com.automattic.tracks:experimentation` | Kotlin | ExPlat A/B testing SDK with file-based caching and OkHttp REST client | +| `crashlogging` | `com.automattic.tracks:crashlogging` | Kotlin | Sentry-based crash logging, performance monitoring, and error tracking | +| `sampletracksapp` | — | Kotlin | Sample app demonstrating library usage | +| `benchmark` | — | Kotlin | Performance benchmarking | + +### Key architectural details + +- **AutomatticTracks** uses a queue-based architecture with background threads for event buffering, DB-to-network transfer, and network transmission. Events expire after 14 days. +- **experimentation** has `explicitApi()` enabled and uses binary compatibility validation (`apiCheck`). Public API surface is tracked in `experimentation/api/experimentation.api`. +- **crashlogging** wraps Sentry SDK via `SentryErrorTrackerWrapper` and exposes a `CrashLoggingDataProvider` interface for host apps to supply user/app context. +- Modules publish independently to S3. No product flavors or build variants. + +## Testing Conventions + +- **Frameworks:** JUnit 4, AssertJ, Mockito-Kotlin, kotlinx-coroutines-test, MockWebServer +- **Assertions:** Use AssertJ (`assertThat`), not kotlin.test assertions +- **Naming:** Backtick-quoted names: `` `given ..., when ..., then ...` `` +- **Coroutines:** Use `runTest` from `kotlinx.coroutines.test` + +## Important Gotchas + +- Build files use **Groovy** (`build.gradle`, `settings.gradle`), not Kotlin DSL +- Dependency versions are defined as `ext` properties in root `build.gradle`, not a version catalog +- Lint treats warnings as errors (`warningsAsErrors true`). `AutomatticTracks` uses a lint baseline file +- CI runs `./gradlew lint ciktlint` (not `lintDebug`) — the `ciktlint` task is from `ktlint.gradle` + +## Publishing + +CI publishes on every PR commit and trunk merge: +- PR: `{pr-number}-{commit-full-sha1}` +- Trunk merge: `trunk-{commit-full-sha1}` +- Tag: `{tag-name}` From 982b782f80358e2b3c47493eaaab245ce7bd5dc5 Mon Sep 17 00:00:00 2001 From: Petros Paraskevopoulos Date: Wed, 4 Mar 2026 12:29:44 +0200 Subject: [PATCH 2/6] AI: Add agents.md and update claude.md to reference it Guide: https://fieldguide.automattic.com/coding-agents-guidelines Move project guidance content into AGENTS.md as the single source of truth for all coding agents, per the Fieldguide coding agents guidelines. Update CLAUDE.md to reference AGENTS.md via the @AGENTS.md directive. Co-Authored-By: Claude Opus 4.6 --- AGENTS.md | 67 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ CLAUDE.md | 68 +------------------------------------------------------ 2 files changed, 68 insertions(+), 67 deletions(-) create mode 100644 AGENTS.md diff --git a/AGENTS.md b/AGENTS.md new file mode 100644 index 0000000..c225afb --- /dev/null +++ b/AGENTS.md @@ -0,0 +1,67 @@ +# CLAUDE.md + +This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository. + +## Project Overview + +Android client library for tracking user events (Nosara/Tracks), A/B testing (ExPlat), and crash logging (Sentry). Published to Automattic's S3 Maven repository. Used internally by Automattic mobile apps. + +## Build Commands + +```bash +./gradlew assembleDebug # Build all modules +./gradlew testDebugUnitTest # Run all unit tests +./gradlew lintDebug # Run lint checks +./gradlew ciktlint # Run ktlint checks +./gradlew buildHealth # Dependency analysis +./gradlew :experimentation:apiCheck # Binary compatibility check (experimentation only) +``` + +To run a single test class: + +```bash +./gradlew :experimentation:testDebugUnitTest --tests "com.automattic.android.experimentation.ExPlatTest" +./gradlew :crashlogging:testDebugUnitTest --tests "com.automattic.android.tracks.crashlogging.SentryCrashLoggingTest" +``` + +**Note:** `gradle.properties` is gitignored. CI copies `gradle.properties-example` before building. Locally, copy it manually if needed: `cp gradle.properties-example gradle.properties`. + +## Architecture + +Three independently published library modules plus a sample app and benchmark module: + +| Module | Artifact | Language | Description | +|--------|----------|----------|-------------| +| `AutomatticTracks` | `com.automattic:Automattic-Tracks-Android` | Java + Kotlin | Core event tracking with SQLite storage and background network transmission | +| `experimentation` | `com.automattic.tracks:experimentation` | Kotlin | ExPlat A/B testing SDK with file-based caching and OkHttp REST client | +| `crashlogging` | `com.automattic.tracks:crashlogging` | Kotlin | Sentry-based crash logging, performance monitoring, and error tracking | +| `sampletracksapp` | — | Kotlin | Sample app demonstrating library usage | +| `benchmark` | — | Kotlin | Performance benchmarking | + +### Key architectural details + +- **AutomatticTracks** uses a queue-based architecture with background threads for event buffering, DB-to-network transfer, and network transmission. Events expire after 14 days. +- **experimentation** has `explicitApi()` enabled and uses binary compatibility validation (`apiCheck`). Public API surface is tracked in `experimentation/api/experimentation.api`. +- **crashlogging** wraps Sentry SDK via `SentryErrorTrackerWrapper` and exposes a `CrashLoggingDataProvider` interface for host apps to supply user/app context. +- Modules publish independently to S3. No product flavors or build variants. + +## Testing Conventions + +- **Frameworks:** JUnit 4, AssertJ, Mockito-Kotlin, kotlinx-coroutines-test, MockWebServer +- **Assertions:** Use AssertJ (`assertThat`), not kotlin.test assertions +- **Naming:** Backtick-quoted names: `` `given ..., when ..., then ...` `` +- **Coroutines:** Use `runTest` from `kotlinx.coroutines.test` + +## Important Gotchas + +- Build files use **Groovy** (`build.gradle`, `settings.gradle`), not Kotlin DSL +- Dependency versions are defined as `ext` properties in root `build.gradle`, not a version catalog +- Lint treats warnings as errors (`warningsAsErrors true`). `AutomatticTracks` uses a lint baseline file +- CI runs `./gradlew lint ciktlint` (not `lintDebug`) — the `ciktlint` task is from `ktlint.gradle` + +## Publishing + +CI publishes on every PR commit and trunk merge: +- PR: `{pr-number}-{commit-full-sha1}` +- Trunk merge: `trunk-{commit-full-sha1}` +- Tag: `{tag-name}` diff --git a/CLAUDE.md b/CLAUDE.md index c225afb..43c994c 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -1,67 +1 @@ -# CLAUDE.md - -This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository. - -## Project Overview - -Android client library for tracking user events (Nosara/Tracks), A/B testing (ExPlat), and crash logging (Sentry). Published to Automattic's S3 Maven repository. Used internally by Automattic mobile apps. - -## Build Commands - -```bash -./gradlew assembleDebug # Build all modules -./gradlew testDebugUnitTest # Run all unit tests -./gradlew lintDebug # Run lint checks -./gradlew ciktlint # Run ktlint checks -./gradlew buildHealth # Dependency analysis -./gradlew :experimentation:apiCheck # Binary compatibility check (experimentation only) -``` - -To run a single test class: - -```bash -./gradlew :experimentation:testDebugUnitTest --tests "com.automattic.android.experimentation.ExPlatTest" -./gradlew :crashlogging:testDebugUnitTest --tests "com.automattic.android.tracks.crashlogging.SentryCrashLoggingTest" -``` - -**Note:** `gradle.properties` is gitignored. CI copies `gradle.properties-example` before building. Locally, copy it manually if needed: `cp gradle.properties-example gradle.properties`. - -## Architecture - -Three independently published library modules plus a sample app and benchmark module: - -| Module | Artifact | Language | Description | -|--------|----------|----------|-------------| -| `AutomatticTracks` | `com.automattic:Automattic-Tracks-Android` | Java + Kotlin | Core event tracking with SQLite storage and background network transmission | -| `experimentation` | `com.automattic.tracks:experimentation` | Kotlin | ExPlat A/B testing SDK with file-based caching and OkHttp REST client | -| `crashlogging` | `com.automattic.tracks:crashlogging` | Kotlin | Sentry-based crash logging, performance monitoring, and error tracking | -| `sampletracksapp` | — | Kotlin | Sample app demonstrating library usage | -| `benchmark` | — | Kotlin | Performance benchmarking | - -### Key architectural details - -- **AutomatticTracks** uses a queue-based architecture with background threads for event buffering, DB-to-network transfer, and network transmission. Events expire after 14 days. -- **experimentation** has `explicitApi()` enabled and uses binary compatibility validation (`apiCheck`). Public API surface is tracked in `experimentation/api/experimentation.api`. -- **crashlogging** wraps Sentry SDK via `SentryErrorTrackerWrapper` and exposes a `CrashLoggingDataProvider` interface for host apps to supply user/app context. -- Modules publish independently to S3. No product flavors or build variants. - -## Testing Conventions - -- **Frameworks:** JUnit 4, AssertJ, Mockito-Kotlin, kotlinx-coroutines-test, MockWebServer -- **Assertions:** Use AssertJ (`assertThat`), not kotlin.test assertions -- **Naming:** Backtick-quoted names: `` `given ..., when ..., then ...` `` -- **Coroutines:** Use `runTest` from `kotlinx.coroutines.test` - -## Important Gotchas - -- Build files use **Groovy** (`build.gradle`, `settings.gradle`), not Kotlin DSL -- Dependency versions are defined as `ext` properties in root `build.gradle`, not a version catalog -- Lint treats warnings as errors (`warningsAsErrors true`). `AutomatticTracks` uses a lint baseline file -- CI runs `./gradlew lint ciktlint` (not `lintDebug`) — the `ciktlint` task is from `ktlint.gradle` - -## Publishing - -CI publishes on every PR commit and trunk merge: -- PR: `{pr-number}-{commit-full-sha1}` -- Trunk merge: `trunk-{commit-full-sha1}` -- Tag: `{tag-name}` +@AGENTS.md From 0f1a58546613956516bb0508e137e9248b3bb7c7 Mon Sep 17 00:00:00 2001 From: Petros Paraskevopoulos Date: Wed, 4 Mar 2026 12:46:28 +0200 Subject: [PATCH 3/6] AI: Update agents.md heading and expand build commands Update AGENTS.md to use agent-agnostic heading and description. Add ktlint, ktlintFormat custom tasks with source reference, benchmark androidTest tasks, sample app mention, and clarify experimentation module name in apiCheck comment. Co-Authored-By: Claude Opus 4.6 --- AGENTS.md | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) diff --git a/AGENTS.md b/AGENTS.md index c225afb..9107feb 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -1,10 +1,10 @@ -# CLAUDE.md +# AGENTS.md -This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository. +This file provides guidance to coding agents when working with code in this repository. ## Project Overview -Android client library for tracking user events (Nosara/Tracks), A/B testing (ExPlat), and crash logging (Sentry). Published to Automattic's S3 Maven repository. Used internally by Automattic mobile apps. +Android client library for tracking user events (Nosara/Tracks), A/B testing (ExPlat), and crash logging (Sentry). Published to Automattic's S3 Maven repository. Used internally by Automattic mobile apps. Includes a `sampletracksapp` app module that can be used for manual testing. ## Build Commands @@ -12,9 +12,13 @@ Android client library for tracking user events (Nosara/Tracks), A/B testing (Ex ./gradlew assembleDebug # Build all modules ./gradlew testDebugUnitTest # Run all unit tests ./gradlew lintDebug # Run lint checks -./gradlew ciktlint # Run ktlint checks +./gradlew ktlint # Check Kotlin code style (custom task from ktlint.gradle) +./gradlew ktlintFormat # Fix Kotlin code style deviations (custom task from ktlint.gradle) +./gradlew ciktlint # Same as ktlint but with checkstyle XML output for CI (custom task from ktlint.gradle) ./gradlew buildHealth # Dependency analysis -./gradlew :experimentation:apiCheck # Binary compatibility check (experimentation only) +./gradlew :experimentation:apiCheck # Binary compatibility check (`experimentation` module only) +./gradlew :benchmark:assembleDebugAndroidTest # Build benchmark instrumented tests +./gradlew :benchmark:connectedDebugAndroidTest # Run benchmark instrumented tests on a connected device ``` To run a single test class: @@ -36,7 +40,7 @@ Three independently published library modules plus a sample app and benchmark mo | `experimentation` | `com.automattic.tracks:experimentation` | Kotlin | ExPlat A/B testing SDK with file-based caching and OkHttp REST client | | `crashlogging` | `com.automattic.tracks:crashlogging` | Kotlin | Sentry-based crash logging, performance monitoring, and error tracking | | `sampletracksapp` | — | Kotlin | Sample app demonstrating library usage | -| `benchmark` | — | Kotlin | Performance benchmarking | +| `benchmark` | — | Kotlin | Performance benchmarking via `androidTest` instrumented tests using `androidx.benchmark` | ### Key architectural details @@ -54,10 +58,9 @@ Three independently published library modules plus a sample app and benchmark mo ## Important Gotchas -- Build files use **Groovy** (`build.gradle`, `settings.gradle`), not Kotlin DSL +- Build files use **Groovy** (`build.gradle`, `settings.gradle`), not Kotlin DSL — except `benchmark/build.gradle.kts` which uses Kotlin DSL - Dependency versions are defined as `ext` properties in root `build.gradle`, not a version catalog - Lint treats warnings as errors (`warningsAsErrors true`). `AutomatticTracks` uses a lint baseline file -- CI runs `./gradlew lint ciktlint` (not `lintDebug`) — the `ciktlint` task is from `ktlint.gradle` ## Publishing From c3735cbba2e3bb07a41ea8de6535f08ca45c80eb Mon Sep 17 00:00:00 2001 From: Petros Paraskevopoulos Date: Wed, 4 Mar 2026 12:52:44 +0200 Subject: [PATCH 4/6] AI: Add .aiexclude to restrict agent access to build artifacts Add .aiexclude file to prevent coding agents from reading build outputs, gradle caches, and local/gradle properties while allowing access to reports, outputs, and test results. Co-Authored-By: Claude Opus 4.6 --- .aiexclude | 9 +++++++++ 1 file changed, 9 insertions(+) create mode 100644 .aiexclude diff --git a/.aiexclude b/.aiexclude new file mode 100644 index 0000000..aa57bd0 --- /dev/null +++ b/.aiexclude @@ -0,0 +1,9 @@ +.gradle/ +build/ +!build/reports/ +*/build/ +!*/build/reports/ +!*/build/outputs/ +!*/build/test-results/ +local.properties +gradle.properties From 23414007c410642960074573739d27808c03257c Mon Sep 17 00:00:00 2001 From: Petros Paraskevopoulos Date: Wed, 4 Mar 2026 12:54:00 +0200 Subject: [PATCH 5/6] Git: Update .gitignore with agent config local overrides Add gitignore patterns for coding agent local override files. Covers AGENTS.local.md and CLAUDE.local.md for repo-level overrides, plus local files for Claude, Codex, Gemini, Cursor, and Windsurf agent directories. Junie and Copilot are excluded as Junie's entire directory is local and Copilot has no local override pattern. Co-Authored-By: Claude Opus 4.6 --- .gitignore | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/.gitignore b/.gitignore index 6498d2a..d1ed73f 100644 --- a/.gitignore +++ b/.gitignore @@ -47,3 +47,13 @@ gradle.properties # OS X generated file .DS_Store +# Agent config local files (Claude, Codex, Gemini, Cursor, Windsurf, etc.) +# Keep main config files under version control, ignore user-local overrides +**/AGENTS.local.md +**/CLAUDE.local.md +**/.claude/**/*.local.* +**/.codex/**/*.local.* +**/.gemini/**/*.local.* +**/.cursor/**/*.local.* +**/.windsurf/**/*.local.* + From f2d69b64d0d24878b92c4494ae9c94496a12bdb3 Mon Sep 17 00:00:00 2001 From: Petros Paraskevopoulos Date: Wed, 4 Mar 2026 12:58:17 +0200 Subject: [PATCH 6/6] Git: Remove duplicate intellij project files block Co-Authored-By: Claude Opus 4.6 --- .gitignore | 6 ------ 1 file changed, 6 deletions(-) diff --git a/.gitignore b/.gitignore index d1ed73f..9a8ba20 100644 --- a/.gitignore +++ b/.gitignore @@ -31,12 +31,6 @@ proguard/ # Log Files *.log -# Intellij project files -*.iml -*.ipr -*.iws -.idea/ - # private config file gradle.properties !/benchmark/gradle.properties