Skip to content

chore(agents): add AI rule files, Gemini styleguide, Copilot wiring#156

Open
vladjerca wants to merge 1 commit into
mainfrom
chore/agents-styleguide-rules
Open

chore(agents): add AI rule files, Gemini styleguide, Copilot wiring#156
vladjerca wants to merge 1 commit into
mainfrom
chore/agents-styleguide-rules

Conversation

@vladjerca
Copy link
Copy Markdown
Contributor

Draft. AFK-friendly - feel free to nudge or close.

Summary

Ports the AI-coding / review stack from trakt-apple-internal to the Android monorepo, tailored to this stack (Compose + Koin + Ktor + OpenAPI + DataStore + Coil 3 + ktlint). Mirrors the structure we already use on trakt-web.

What lands:

  • .agents/rules/*.md (13 files) - project, code-principles, implementation, architecture, state-management, networking, persistence, theming, localization, testing, packages, legacy-zones, commits.
  • AGENTS.md at the root - @-includes the rule files in order.
  • CLAUDE.md - symlink to AGENTS.md, so Claude Code loads the same stack.
  • .gemini/styleguide.md - Gemini-flavoured digest of the same rules. The existing .gemini/config.yaml ignore_patterns grew to skip build/, external/, generated OpenAPI sources, and Crowdin-managed translation files.
  • .github/copilot-instructions.md - symlink to ../AGENTS.md so GitHub Copilot picks up the same rules.

No source code touched. No build.gradle.kts, .editorconfig, or workflow changes - those stay as-is.

Reference projects synthesised

  • android/nowinandroid - Google's canonical Compose sample. Modular layout (:feature:foo:{api,impl} + :core:foo), Hilt-based but the architecture and testing rules (no mocking libs, screenshot tests via Roborazzi) carry over.
  • chrisbanes/tivi - Trakt-domain match (TV/movie tracking, archived Nov 2024). Confirmed many of our existing choices (Coil 3, Ktor, per-entity data slicing).
  • DroidKaigi/conference-app-2024 - modern community patterns; provided the testing direction (Robolectric + Roborazzi + Robot pattern), detekt as a possible secondary linter, and the Compose-presenter experiment we deliberately do not adopt.

Direction the rules describe (for new code)

  • MVVM + UDF. ViewModels expose StateFlow<UiState> built via stateIn(viewModelScope, WhileSubscribed(5_000), Initial).
  • Sealed UiState (Loading / Loaded(...) / Error(...)) - not flat data classes with three nullable fields.
  • StateFlow only inside ViewModels. No mutableStateOf in ViewModels (Compose-coupled, hard to test).
  • Screen (stateful) + Content (stateless) split. Previews target the Content variant.
  • Compose Navigation 2.9+ with @Serializable typed routes. No string-route DSL for new screens.
  • Koin with constructor injection. single / factory / viewModel scopes per the rules. No third-party DI library switch planned.
  • Repositories expose Flow<T> reads + suspend fun writes returning Result<T>.
  • OpenAPI client generated - never hand-edited. Hand-written mappers translate DTOs to domain models.
  • Status 204 is success - mappers handle 204 by returning empty/default values.
  • DataStore for prefs; no SharedPreferences direct usage in new code.
  • All visuals through TraktTheme.* tokens - no raw Color(0xFF...), no Modifier.padding(16.dp) magic numbers.
  • Conventional Commits with android-scoped enum (app, tv, common, resources, openapi, widget, i18n, ci, deps, gradle, agents, gemini).

Forward-only posture

The codebase is already in much better shape than the apple side - Compose-only, no XML/Fragments/LiveData/RxJava, conventional commits in use, ktlint wired into CI. Rules document the modern path; the only "legacy zones" worth carving out are generated paths (build/generate-resources/, Crowdin-managed values-*/strings.xml, external/).

What this PR does NOT do

  • Touch any Kotlin source.
  • Modify any build.gradle.kts, the version catalogue, or .editorconfig.
  • Introduce Detekt (the rules mention it as a possible future direction).
  • Introduce Roborazzi screenshot tests (same).
  • Flip CI to enforce additional linting.

These are all deliberate follow-ups. The goal here is to land docs + configs so reviewers and AI agents share a vocabulary.

Test plan

  • Markdown files render in GitHub preview.
  • .gemini/config.yaml parses (YAML.load_file).
  • CLAUDE.md and .github/copilot-instructions.md symlinks resolve to AGENTS.md.
  • All 13 rule files exist under .agents/rules/.
  • Open Claude Code in the repo root and confirm rules load.
  • Open a small follow-up PR and confirm Gemini review respects the new .gemini/styleguide.md + ignore_patterns.

Relation to trakt-apple-internal

Parallels trakt/trakt-apple-internal#132. Architecture choices diverge on:

  • DI: apple uses init-injection (no library); android uses Koin (already in use).
  • Per-screen ViewModels: apple does not require them (IceCubes path); android does (ViewModel survives config change).
  • Module layout: both flat today; per-feature modules allowed-not-mandated on both sides.
  • Concurrency: apple targets Swift 6 mode; android already on Kotlin 2.x with coroutines.

@gemini-code-assist
Copy link
Copy Markdown

Summary of Changes

Hello, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

This pull request introduces a structured AI-coding and review stack to the Android monorepo, mirroring the architecture and principles used in other internal projects. By providing a centralized set of rules for architecture, state management, networking, and testing, it ensures that both human developers and AI agents share a consistent vocabulary and set of best practices. The changes are purely documentation and configuration-based, intended to guide future development without modifying existing source code.

Highlights

  • AI Rule Documentation: Added a comprehensive suite of rule files under .agents/rules/ to standardize development practices across architecture, state management, networking, and testing.
  • AI Assistant Configuration: Configured Claude Code, GitHub Copilot, and Gemini with project-specific style guides and constraints to ensure consistent AI-assisted coding.
  • Forward-only Posture: Established a clear set of modern development guidelines (MVVM, UDF, Koin, Compose) while documenting legacy zones to guide future refactoring.
Ignored Files
  • Ignored by pattern: .gemini/** (2)
    • .gemini/config.yaml
    • .gemini/styleguide.md
Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize the Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counterproductive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for GitHub and other Google products, sign up here.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

Copy link
Copy Markdown

@gemini-code-assist gemini-code-assist Bot left a comment

Choose a reason for hiding this comment

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

Code Review

This pull request introduces a comprehensive suite of documentation and rules for AI agents in the .agents/ directory, detailing the project's architecture, design principles, and technical constraints for the Trakt Android application. The review feedback correctly identifies a naming convention for acronyms that conflicts with standard Kotlin style, points out the presence of placeholder version numbers that may cause AI hallucinations, and flags an architectural inconsistency in a localization example that incorrectly uses Context.

Comment thread .agents/rules/implementation.md Outdated
Comment thread .agents/rules/project.md
Comment thread .agents/rules/localization.md Outdated
@michaldrabik
Copy link
Copy Markdown
Collaborator

Won't hurt anyone probably but will check later :

@vladjerca
Copy link
Copy Markdown
Contributor Author

Won't hurt anyone probably but will check later :

That's why I drafted it's still under review for me I want to get more things ironed out.

@vladjerca
Copy link
Copy Markdown
Contributor Author

Second pass landed in 2db1898d. Deep-dived android/nowinandroid, chrisbanes/tivi, and element-hq/element-x-android, then folded the gaps into the rule files.

Highlights:

  • architecture.md: explicit invariants block (events down, data up, local SoT, repository owns its domain models). New "Background sync" section with CoroutineWorker + WorkManager backoff. New "Adaptive layouts" section using WindowSizeClass.
  • networking.md: local-write-first repository rule made explicit (no remote-only emission paths).
  • state-management.md: new "Compose stability" section + a compose-stability.conf at the repo root listing Trakt domain types and stable third-party types. @Immutable vs @Stable distinction documented.
  • packages.md: convention-plugins section listing target aliases (trakt.android.application, trakt.android.library.compose, trakt.android.feature, trakt.android.lint, trakt.jvm.library). New "Lint" section with per-module lint-baseline.xml policy ("the baseline never grows from a PR"). Spotless flagged as aspirational.
  • testing.md: MainDispatcherRule snippet, multi-config preview annotations (@PreviewLightDark, @PreviewFontScale), screenshot tests via Paparazzi + ComposablePreviewScanner with "baselines from CI only" rule, Konsist architecture tests, baseline profiles + :benchmarks module.
  • theming.md: Coil 3 specifics - SubcomposeAsyncImage, stable request keys, shared ImageLoader single, custom interceptor location.
  • code-principles.md: @JvmInline value class for typed IDs (MovieId, EpisodeId, Slug).
  • legacy-zones.md: alternatives evaluated and not adopted (kotlin-inject, Hilt, Metro, Circuit, Appyx, SQLDelight, Room). DataBinding / ViewBinding forbidden in new code.
  • project.md: logging discipline (lazy formatting, no android.util.Log.*, no PII).

Also applied Gemini's three review comments (acronyms → official Kotlin style, episodeTypeLabel → @StringRes Int?). Inline replies on the threads.

Out-of-scope for this PR, but called out in the rules as follow-ups:

  • build-logic/convention/ plugin migration.
  • Spotless wiring.
  • Konsist suite and baseline-profile scaffolding.
  • :benchmarks module.
  • Paparazzi + CI-recorded snapshot baselines.

Ready to undraft. 👀

@vladjerca vladjerca marked this pull request as ready for review May 19, 2026 15:35
Introduces a `.agents/rules/*.md` set (13 files), root `AGENTS.md` +
`CLAUDE.md`, a Gemini styleguide alongside the existing config, and a
`.github/copilot-instructions.md` symlink to `AGENTS.md` so GitHub
Copilot picks up the same rules. Tailored to this stack: Compose-only,
Koin DI, Ktor + OpenAPI-generated client, Coil 3, DataStore, ktlint.

Reference projects synthesised:
- android/nowinandroid - Google's canonical modular Compose sample.
- chrisbanes/tivi - Trakt-domain match (TV/movie tracking, KMP).
- DroidKaigi/conference-app-2024 - modern community patterns.
- element-hq/element-x-android - enterprise Compose Matrix client.

Direction the rules describe (for new code):

- MVVM + UDF. ViewModels expose `StateFlow<UiState>` via
  `stateIn(viewModelScope, WhileSubscribed(5_000), Initial)`.
- Sealed `UiState` (Loading / Loaded / Error), Screen + Content split.
- Compose Navigation 2.9+ with `@Serializable` typed routes.
- Koin DI with constructor injection. No Hilt, no Dagger.
- Repositories: `Flow<T>` reads, `suspend` writes returning `Result`.
  Local-write-first invariant (offline-first).
- OpenAPI client generated; mappers translate DTOs to domain models.
- Status 204 is success.
- DataStore for prefs; no `SharedPreferences` in new code.
- All visuals via `TraktTheme.*` tokens.
- Conventional Commits with android-scoped enum.

Forward-only posture: rules govern new code and substantially
rewritten files. Generated paths (`build/`, `external/`, OpenAPI
output, Crowdin-managed translation files) are out-of-scope per
`legacy-zones.md`.

Includes:

- YAML frontmatter (`trigger: glob`, `applyTo: <glob>`) on every rule
  file so tools that support glob-based lazy loading only pull a rule
  when an edited file matches its scope. AGENTS.md still
  `@`-includes the full set for tools that need the complete context.
- Per-subproject `CLAUDE.md` shells for `app/`, `tv/`, `common/`,
  `resources/` matching the apple sibling's layout.
- `compose-stability.conf` at repo root listing Trakt domain types
  and stable third-party types for the Compose compiler.
- Architecture deep-dive material from the second-pass review of NIA,
  Tivi, and element-x-android (invariants block, background sync,
  adaptive layouts, Compose stability, convention plugins, per-module
  lint baselines, MainDispatcherRule, multi-config previews,
  screenshot tests via Paparazzi + ComposablePreviewScanner, Konsist,
  baseline profiles, Coil 3 specifics, typed IDs, alternatives
  evaluated, logging discipline).

Adopts Gemini's review feedback:
- Acronyms follow official Kotlin style (Url / Id / Json).
- `episodeTypeLabel` returns `@StringRes Int?` rather than taking
  `Context` - keeps the mapper pure and ViewModel-safe.
@vladjerca vladjerca force-pushed the chore/agents-styleguide-rules branch from 2db1898 to da83e96 Compare May 19, 2026 16:00
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.

2 participants