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>
5.6 KiB
5.6 KiB
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 containingModuleTypeenum (LINE_CORRIDOR, PRESSURE_RAMP, CURVE_SCULPTOR, VECTOR_SNAP) - Created
core/GameHost.kt— routes by ModuleType, exposesonSessionCompletecallback - 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)
LineCorridorScreenrenders 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: Booleanadded toStylusFrame; DOWN/UP edge detection for clean session start/stop- Android Y flipped to LibGDX coordinate space in
processInput() LineScorecomputed: straightness (RMS perpendicular deviation) + pressureConsistency (RMS from 0.5)- Full result pipeline: GL thread →
runOnUiThread { setResult + finish() }→ActivityResultLauncher→lastScoreCompose state →ScoreCardonModuleDetailScreen - "Start Training" button changes to "Train Again" after first session
Build environment fixed
- Added
gradlewscript (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.propertiescreated:sdk.dir=/opt/homebrew/share/android-commandlinetools
- SDK root:
- Fixed
copyAndroidNativestask — now extracts each.sointo its ABI subdirectory (libs/arm64-v8a/, etc.) - Symlink at
/opt/homebrew/opt/jbr-home→ IntelliJ JBR (used for sdkmanager)
Build command (verified working)
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.ArrowBackdeprecated → useIcons.AutoMirrored.Filled.ArrowBack- Affects:
ModuleDetailScreen.kt,ProgressScreen.kt,SettingsScreen.kt
Next Steps (Priority Order)
Immediate
-
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
-
Fix ArrowBack deprecation (3 files, 1-line change each):
// Old Icons.Default.ArrowBack // New Icons.AutoMirrored.Filled.ArrowBack // Also add import: import androidx.compose.material.icons.automirrored.filled.ArrowBack
Phase 1 (ROADMAP)
- Corridor difficulty progression (narrowing half-width per session)
- Session summary screen (score + streak counter)
- Local score persistence (DataStore or Room)
- Progress screen populated with real data (last 7 sessions chart)
Phase 2
- 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 {}beforesetResult/finish - The
natives-desktopJAR is skipped bycopyAndroidNatives(not in thevalidAbisset) — this is intentional