Files
Kanbn4droid/AGENTS.md
2026-03-18 14:54:16 -04:00

165 lines
6.5 KiB
Markdown

# AGENTS.md
This file is for agentic coding assistants working in this repository.
It captures build/test commands and code conventions observed in the codebase.
## Project Snapshot
- Name: `Kanbn4Droid`
- Platform: Android app (Kotlin, XML views, coroutines)
- Build system: Gradle Kotlin DSL (`*.gradle.kts`)
- Module layout: single app module `:app`
- Namespace/application id: `space.hackenslacker.kanbn4droid.app`
- Compile/target SDK: 35
- Min SDK: 29
- Java/Kotlin target: 17
## Environment Prerequisites
- Java 17 installed and available on PATH
- Android SDK command-line tools installed
- Android SDK packages:
- `platforms;android-35`
- `build-tools;35.0.0`
- `platform-tools`
- If SDK is not auto-detected, copy `local.properties.example` to `local.properties` and set `sdk.dir`
## Source of Truth for Commands
- Prefer Gradle wrapper (`./gradlew`) over system Gradle
- Most Android tasks should be run with explicit module prefix when possible (`:app:<task>`)
- Discover tasks with: `./gradlew tasks --all`
## Build / Lint / Test Commands
### Core Daily Commands
- List tasks: `./gradlew tasks --all`
- Clean: `./gradlew clean`
- Build everything in app module: `./gradlew :app:build`
- Build debug APK: `./gradlew :app:assembleDebug`
- Install debug APK on connected device/emulator: `./gradlew :app:installDebug`
### Lint
- Run default lint: `./gradlew :app:lint`
- Run debug lint explicitly: `./gradlew :app:lintDebug`
- Run release lint explicitly: `./gradlew :app:lintRelease`
- Auto-fix safe lint issues: `./gradlew :app:lintFix`
### Unit Tests (JVM)
- Run all unit tests (all variants): `./gradlew :app:test`
- Run debug unit tests: `./gradlew :app:testDebugUnitTest`
- Run release unit tests: `./gradlew :app:testReleaseUnitTest`
### Run a Single Unit Test (important)
- Single test class:
- `./gradlew :app:testDebugUnitTest --tests "space.hackenslacker.kanbn4droid.app.boards.BoardsViewModelTest"`
- Single test method:
- `./gradlew :app:testDebugUnitTest --tests "space.hackenslacker.kanbn4droid.app.boards.BoardsViewModelTest.createBoardSuccessEmitsNavigateEvent"`
- Pattern match within class/package:
- `./gradlew :app:testDebugUnitTest --tests "space.hackenslacker.kanbn4droid.app.boarddetail.*"`
### Instrumentation Tests (device/emulator required)
- Run all connected debug instrumentation tests:
- `./gradlew :app:connectedDebugAndroidTest`
- Equivalent aggregate task:
- `./gradlew :app:connectedAndroidTest`
### Run a Single Instrumentation Test (important)
- Single instrumentation test class:
- `./gradlew :app:connectedDebugAndroidTest -Pandroid.testInstrumentationRunnerArguments.class=space.hackenslacker.kanbn4droid.app.BoardsFlowTest`
- Single instrumentation test method:
- `./gradlew :app:connectedDebugAndroidTest -Pandroid.testInstrumentationRunnerArguments.class=space.hackenslacker.kanbn4droid.app.BoardsFlowTest#pullToRefreshWorks`
## Repository-Local Rules (Cursor/Copilot)
- Checked for Cursor rules in `.cursor/rules/` and `.cursorrules`: none found
- Checked for Copilot instructions in `.github/copilot-instructions.md`: none found
- Therefore, no additional repo-local AI instruction files are currently enforced beyond this document
- If those files are added later, treat them as higher-priority guidance and update this AGENTS.md
## Architecture and Code Organization
- UI is Activity-driven (not Compose)
- Feature folders under `app/src/main/java/space/hackenslacker/kanbn4droid/app/`: `auth/`, `boards/`, `boarddetail/`, `carddetail/`
- Typical layering:
- Activity handles view binding and user interaction wiring
- ViewModel holds UI state and events (`StateFlow` + `SharedFlow`)
- Repository/data source handles session and API calls
- API client encapsulates HTTP + response parsing
## Kotlin Style Guidelines (observed conventions)
### Formatting
- Follow Kotlin official code style (`gradle.properties: kotlin.code.style=official`)
- Use 4-space indentation
- Use trailing commas in multiline argument lists/constructors where already used
- Keep functions focused; prefer extraction for repeated logic
- Avoid unnecessary comments; use clear naming instead
### Imports
- Do not use wildcard imports
- Keep imports grouped (platform/library/project), matching existing file style
- Remove unused imports
- Prefer explicit imports for readability in large files
### Types and API design
- Prefer immutable `val`; use `var` only when mutation is required
- Use data classes for immutable UI/domain models
- Use sealed interfaces/classes for event/result hierarchies (`BoardsUiEvent`, mutation results)
- Keep nullability explicit; avoid nullable types unless required by API/domain
- Return domain/result wrappers instead of throwing for expected failures
### Naming
- Packages: lowercase, dot-separated (`space.hackenslacker...`)
- Classes/interfaces/objects: PascalCase
- Functions/properties/locals: camelCase
- Constants: UPPER_SNAKE_CASE (`private const val ...`)
- Test method names: descriptive camelCase phrases that state behavior
### Coroutines and threading
- Use `viewModelScope.launch` for ViewModel async work
- Use `withContext(Dispatchers.IO)` or injected IO dispatcher for blocking/network work
- Keep dispatcher injection points testable (repositories already do this)
- Avoid blocking calls on main thread
### State and events
- Model screen state as immutable `data class` in ViewModel
- Update state via copy semantics (`state.copy(...)`), often with `MutableStateFlow.update`
- Use one-off events via `SharedFlow` rather than state flags for navigation/toasts/dialog alerts
- Keep rendering deterministic from current state
### Error handling
- Prefer explicit result types (`BoardsApiResult`, `AuthResult`) over exceptions for normal failure paths
- Surface user-visible messages through UI events/state
- Validate user input early (blank checks, URL normalization) before network calls
### Android/UI conventions
- Keep user-facing text in `res/values/strings.xml` when practical
- Use Material components already present in the project
- Keep Activity responsibilities focused on binding and orchestration, not business logic
- Respect existing navigation via explicit intents and extras constants
## Testing Conventions
- Unit tests live in `app/src/test/...` and use JUnit4 + coroutines test utilities
- Instrumentation tests live in `app/src/androidTest/...` and use Espresso/Intents
- Prefer fakes/in-memory stores for API/session dependencies in tests
- In coroutine tests:
- set/reset main dispatcher in `@Before/@After`
- use `runTest` and `advanceUntilIdle()`
- Keep tests behavior-focused (arrange -> act -> assert)