Full AL-001 through AL-008 implementation: shared/ module with ModuleType enum, GameHost routing, StylusInputBridge, LineCorridorScreen with live stroke rendering, LineScore (straightness + anglePrecision), score returned to Compose hub via ActivityResult. Fixes LineScore field mismatch (pressureConsistency → anglePrecision) caught during AL-009 build check. Adds .gitignore and handoff notes. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
126 lines
5.6 KiB
Markdown
126 lines
5.6 KiB
Markdown
# Agent Handoff — May 5, 2026
|
|
|
|
## Session Summary
|
|
|
|
Full rearchitecture from pure LibGDX to hybrid Compose + LibGDX. Sprint 0 (foundation) and Sprint 1 (Line Corridor MVP) both completed in this session. APK builds successfully.
|
|
|
|
---
|
|
|
|
## What Was Accomplished
|
|
|
|
### Architecture (Sprint 0 — all done)
|
|
- Created `shared/` pure-Kotlin module containing `ModuleType` enum (LINE_CORRIDOR, PRESSURE_RAMP, CURVE_SCULPTOR, VECTOR_SNAP)
|
|
- Created `core/GameHost.kt` — routes by ModuleType, exposes `onSessionComplete` callback
|
|
- Created `core/input/StylusFrame.kt` + `StylusInputBridge.kt` — AtomicReference bridge, GL-thread safe
|
|
- Created `core/modules/LineCorridorScreen.kt` + `LineScore.kt`
|
|
- Created `core/PlaceholderModuleScreen.kt`
|
|
- Created `android/MainActivity.kt` — ComponentActivity + Compose
|
|
- Created `android/GameActivity.kt` — AndroidApplication, reads ModuleType from Intent, sets OnTouchListener on LibGDX view
|
|
- Created full Compose navigation: `ArtLegendApp`, `HubScreen`, `ModuleDetailScreen`, `ProgressScreen`, `SettingsScreen`
|
|
- Created dark Material3 theme (violet #7B2FBE / cyan #00E5FF)
|
|
- Updated `AndroidManifest.xml`: MainActivity as LAUNCHER, GameActivity as landscape fullscreen non-exported
|
|
- Deleted orphaned `AndroidLauncher.kt`, `ArtLegend.kt`, `styles.xml`
|
|
|
|
### Line Corridor (Sprint 1 — all done)
|
|
- `LineCorridorScreen` renders two cyan corridor walls + dashed centerline at random ±25° angle via ShapeRenderer
|
|
- Stroke captured live from StylusInputBridge, rendered in yellow with pressure-driven alpha
|
|
- `isDown: Boolean` added to `StylusFrame`; DOWN/UP edge detection for clean session start/stop
|
|
- Android Y flipped to LibGDX coordinate space in `processInput()`
|
|
- `LineScore` computed: straightness (RMS perpendicular deviation) + pressureConsistency (RMS from 0.5)
|
|
- Full result pipeline: GL thread → `runOnUiThread { setResult + finish() }` → `ActivityResultLauncher` → `lastScore` Compose state → `ScoreCard` on `ModuleDetailScreen`
|
|
- "Start Training" button changes to "Train Again" after first session
|
|
|
|
### Build environment fixed
|
|
- Added `gradlew` script (copied from whisper.cpp) + `gradle-wrapper.jar`
|
|
- Added Foojay toolchain resolver plugin to `settings.gradle.kts` (auto-downloads JDK 17)
|
|
- Installed Android SDK via `brew install --cask android-commandlinetools`
|
|
- SDK root: `/opt/homebrew/share/android-commandlinetools`
|
|
- Installed: `platforms;android-34`, `build-tools;34.0.0`, `platform-tools`
|
|
- `local.properties` created: `sdk.dir=/opt/homebrew/share/android-commandlinetools`
|
|
- Fixed `copyAndroidNatives` task — now extracts each `.so` into its ABI subdirectory (`libs/arm64-v8a/`, etc.)
|
|
- Symlink at `/opt/homebrew/opt/jbr-home` → IntelliJ JBR (used for sdkmanager)
|
|
|
|
### Build command (verified working)
|
|
```bash
|
|
cd /Users/blindmouse/artlegend
|
|
JAVA_HOME="/Users/blindmouse/Applications/IntelliJ IDEA.app/Contents/jbr/Contents/Home" ./gradlew :android:assembleDebug
|
|
```
|
|
APK output: `android/build/outputs/apk/debug/android-debug.apk`
|
|
|
|
---
|
|
|
|
## Current State
|
|
|
|
**SPRINT.md tickets:**
|
|
- AL-001 through AL-008: DONE
|
|
- AL-009 (on-device smoke test): not done — device needed
|
|
|
|
**Three deprecation warnings** (non-blocking, cosmetic):
|
|
- `Icons.Default.ArrowBack` deprecated → use `Icons.AutoMirrored.Filled.ArrowBack`
|
|
- Affects: `ModuleDetailScreen.kt`, `ProgressScreen.kt`, `SettingsScreen.kt`
|
|
|
|
---
|
|
|
|
## Next Steps (Priority Order)
|
|
|
|
### Immediate
|
|
1. **AL-009 on-device test** — install APK, verify:
|
|
- Hub shows 4 module cards
|
|
- Tap → ModuleDetail → "Start Training" → LibGDX corridor renders
|
|
- S-Pen stroke captured, score returned on finish
|
|
- Check logcat: `adb logcat -s LineCorridor GameActivity`
|
|
|
|
2. **Fix ArrowBack deprecation** (3 files, 1-line change each):
|
|
```kotlin
|
|
// Old
|
|
Icons.Default.ArrowBack
|
|
// New
|
|
Icons.AutoMirrored.Filled.ArrowBack
|
|
// Also add import:
|
|
import androidx.compose.material.icons.automirrored.filled.ArrowBack
|
|
```
|
|
|
|
### Phase 1 (ROADMAP)
|
|
3. Corridor difficulty progression (narrowing half-width per session)
|
|
4. Session summary screen (score + streak counter)
|
|
5. Local score persistence (DataStore or Room)
|
|
6. Progress screen populated with real data (last 7 sessions chart)
|
|
|
|
### Phase 2
|
|
7. Pressure Ramp module
|
|
|
|
---
|
|
|
|
## Key File Locations
|
|
|
|
```
|
|
artlegend/
|
|
shared/src/main/kotlin/com/artlegend/shared/ModuleType.kt
|
|
core/src/main/kotlin/com/artlegend/
|
|
GameHost.kt
|
|
PlaceholderModuleScreen.kt
|
|
input/StylusFrame.kt
|
|
input/StylusInputBridge.kt
|
|
modules/LineCorridorScreen.kt
|
|
modules/LineScore.kt
|
|
android/src/main/kotlin/com/artlegend/
|
|
MainActivity.kt
|
|
GameActivity.kt
|
|
ui/ArtLegendApp.kt
|
|
ui/theme/ArtLegendTheme.kt
|
|
ui/screens/{Hub,ModuleDetail,Progress,Settings}Screen.kt
|
|
android/src/main/res/values/themes.xml
|
|
android/src/main/AndroidManifest.xml
|
|
local.properties ← sdk.dir, gitignored
|
|
settings.gradle.kts ← includes foojay toolchain resolver
|
|
SPRINT.md, ROADMAP.md, README.md
|
|
```
|
|
|
|
## Gotchas for Next Agent
|
|
|
|
- **sdkmanager requires** `JAVA_HOME=/opt/homebrew/opt/jbr-home SKIP_JDK_VERSION_CHECK=1` — the JBR version string breaks the integer test in the wrapper script
|
|
- **StylusInputBridge** is last-write-wins (AtomicReference.set), not a queue — fine for 60fps render but means missed frames between renders are dropped
|
|
- **Y-coordinate flip**: StylusFrame stores raw Android Y (top=0); LineCorridorScreen flips it to LibGDX space (bottom=0) in `processInput()`
|
|
- **GameActivity.onSessionComplete** is called on the GL thread — always `runOnUiThread {}` before `setResult/finish`
|
|
- The `natives-desktop` JAR is skipped by `copyAndroidNatives` (not in the `validAbis` set) — this is intentional
|