165 lines
6.5 KiB
Markdown
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)
|