6.5 KiB
6.5 KiB
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-35build-tools;35.0.0platform-tools
- If SDK is not auto-detected, copy
local.properties.exampletolocal.propertiesand setsdk.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; usevaronly 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.launchfor 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 classin ViewModel - Update state via copy semantics (
state.copy(...)), often withMutableStateFlow.update - Use one-off events via
SharedFlowrather 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.xmlwhen 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
runTestandadvanceUntilIdle()
- set/reset main dispatcher in
- Keep tests behavior-focused (arrange -> act -> assert)