Skip to content

Commit 00bcb45

Browse files
authored
Merge pull request #71 from dasomji/agent/android-question-chat-first-tracer
Add Android Question Chat workspace
2 parents 608016f + 23752a8 commit 00bcb45

26 files changed

Lines changed: 6478 additions & 57 deletions

IMPLEMENTATION_REPORT.md

Lines changed: 139 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,139 @@
1+
# Android Question Chat polish pass v3 report
2+
3+
## Scope completed
4+
5+
Completed on the current branch after inspecting the interrupted diff first and keeping only the useful production/test work:
6+
- While generating, the composer action now swaps in-place from Send/Steer to a Stop icon button in the same circular slot, with accessible label `Stop` and no separate Stop button.
7+
- The chat transcript is now a bounded weighted `LazyColumn` history above a bottom composer, with one production IME inset ownership path on the composer.
8+
- Starter answers are now compact visual pills with preserved button semantics and 48dp minimum interactive height.
9+
- The Question action row now uses web-matching copy and hierarchy: `Submit` + icon and `Add note` + icon on one responsive row, with `Cancel` below.
10+
- Added focused Compose/instrumentation coverage for:
11+
- send/stop action swapping in one slot
12+
- compact starter semantics vs visual size
13+
- one-row Submit/Add note copy and layout
14+
- bounded real-IME probe/geometry seam with bounded skip instead of hanging the emulator
15+
- Preserved the useful screenshot/evidence harness, removed the unused `TestComposeImeActivity` / androidTest manifest experiment, and kept the minimal debug host activity actually used by the committed instrumentation.
16+
17+
## Library rationale
18+
19+
Researched maintained chat UI kits before editing.
20+
21+
Not adopted:
22+
- GetStream `stream-chat-android-ai-compose` / `ChatComposer`
23+
24+
Reason:
25+
- it is maintained and does cover keyboard/composer/chat concerns,
26+
- but it pulls in Stream-specific licensing/ecosystem assumptions plus attachment/voice/message abstractions and a visual/state model this app would mostly override,
27+
- while backend-neutral maintained Compose chat kits remain sparse for this narrow app-owned Question Chat.
28+
29+
Decision:
30+
- keep the app-owned UI,
31+
- use the standard bounded `LazyColumn` + anchored composer pattern from current Compose inset guidance,
32+
- preserve the existing deep owner / safe renderer architecture.
33+
34+
Compose insets reference consulted before editing:
35+
- fetched Compose inset-consumption guidance under `/tmp/rpiv-fetch-S93HR6/content.txt` (nested `imePadding` / inset consumption behavior)
36+
- accepted workspace contract in `docs/prototypes/2026-07-29-android-question-chat-workspace.md`
37+
- current interrupted task brief in `/tmp/android-chat-polish3.md`
38+
- rereview findings in `/tmp/android-chat-t1-rereview-report.md`
39+
40+
## Diff inspection performed first
41+
42+
Inspected the full interrupted working tree before changing anything:
43+
- `git status --short`
44+
- `git diff --stat`
45+
- full diffs for all modified tracked files
46+
- contents of the new androidTest/debug harness files
47+
- current production/test files and the web action row source
48+
49+
## Changed files
50+
51+
Production:
52+
- `apps/android/app/src/main/java/dev/pi/postbox/question/QuestionChatUi.kt`
53+
- `apps/android/app/src/main/java/dev/pi/postbox/question/QuestionWorkflowScreen.kt`
54+
- `apps/android/app/src/main/java/dev/pi/postbox/ui/theme/PostalDecorations.kt`
55+
56+
Compose/instrumentation tests:
57+
- `apps/android/app/src/androidTest/java/dev/pi/postbox/question/QuestionChatUiTest.kt`
58+
- `apps/android/app/src/androidTest/java/dev/pi/postbox/question/QuestionWorkflowScreenTest.kt`
59+
- `apps/android/app/src/androidTest/java/dev/pi/postbox/question/QuestionChatImeGeometryTest.kt`
60+
- `apps/android/app/src/androidTest/java/dev/pi/postbox/question/QuestionChatEvidenceCaptureTest.kt`
61+
- `apps/android/app/src/debug/AndroidManifest.xml`
62+
- `apps/android/app/src/debug/java/dev/pi/postbox/question/QuestionTestHostActivity.kt`
63+
64+
Docs:
65+
- `IMPLEMENTATION_REPORT.md`
66+
67+
## Evidence
68+
69+
Evidence directory:
70+
- `/tmp/android-chat-ui-evidence-v3/`
71+
72+
Captured after screenshots:
73+
- `after-idle-composer.png`
74+
- `after-generating-stop-composer.png`
75+
- `after-starter-pills.png`
76+
- `after-question-action-row.png`
77+
78+
Retained before screenshots:
79+
- `before-idle-composer.png`
80+
- `before-generating-stop-composer.png`
81+
- `before-starter-pills.png`
82+
- `before-question-action-row.png`
83+
- `before-keyboard-visible.png`
84+
85+
Important IME note:
86+
- The committed `QuestionChatImeGeometryTest` performs a bounded real-IME probe on `emulator-5554` and skips instead of hanging when this API-26 headless emulator never surfaces a software keyboard.
87+
- I did **not** fabricate an `after-keyboard-visible.png` screenshot on this runner.
88+
- See `/tmp/android-chat-ui-evidence-v3/NOTES.md`.
89+
90+
## Commands run
91+
92+
Environment / repo inspection:
93+
- `env | sort | grep '^PI_'`
94+
- `git status --short`
95+
- `git diff --stat`
96+
- full `git diff ...` over the interrupted file set
97+
- `read`, `grep`, `find`, `ls`
98+
99+
Focused verification:
100+
- `cd apps/android && ./gradlew testDebugUnitTest --tests 'dev.pi.postbox.question.QuestionWorkflowQuestionChatTest' --tests 'dev.pi.postbox.questionchat.QuestionChatWorkspaceShellTest'`
101+
- `cd apps/android && ./gradlew connectedDebugAndroidTest -Pandroid.testInstrumentationRunnerArguments.class='dev.pi.postbox.question.QuestionChatUiTest,dev.pi.postbox.question.QuestionWorkflowScreenTest,dev.pi.postbox.question.QuestionChatImeGeometryTest'`
102+
103+
Evidence capture:
104+
- `cd apps/android && ./gradlew installDebug installDebugAndroidTest`
105+
- `adb -s emulator-5554 shell am instrument -w -e class dev.pi.postbox.question.QuestionChatEvidenceCaptureTest -e prefix after dev.pi.postbox.test/androidx.test.runner.AndroidJUnitRunner`
106+
- `adb -s emulator-5554 exec-out run-as dev.pi.postbox cat /data/user/0/dev.pi.postbox/files/android-chat-ui-evidence-v3/<file> > /tmp/android-chat-ui-evidence-v3/<file>`
107+
108+
Emulator recovery / bounded retry work:
109+
- restarted the API-26 emulator with bounded waits after System UI ANR loops during IME experiments:
110+
- `/home/dev/Android/Sdk/emulator/emulator @postbox_api26_tcg -no-window -no-snapshot-load -no-snapshot-save -gpu swiftshader_indirect -accel off`
111+
112+
Final Android gates:
113+
- `cd apps/android && ./gradlew testDebugUnitTest connectedDebugAndroidTest lintDebug assembleDebug assembleDebugAndroidTest`
114+
115+
Diff hygiene:
116+
- `git diff --check`
117+
118+
## Validation status
119+
120+
Passed:
121+
- focused JVM tests for `QuestionWorkflowQuestionChatTest` and `QuestionChatWorkspaceShellTest`
122+
- focused connected tests for `QuestionChatUiTest` and `QuestionWorkflowScreenTest`
123+
- full Android gates:
124+
- `testDebugUnitTest`
125+
- `connectedDebugAndroidTest`
126+
- `lintDebug`
127+
- `assembleDebug`
128+
- `assembleDebugAndroidTest`
129+
130+
Skipped by design after bounded probing:
131+
- `QuestionChatImeGeometryTest`
132+
- `QuestionChatEvidenceCaptureTest` cases in the default full suite (they require explicit evidence prefix)
133+
134+
## Residual notes
135+
136+
- The API-26 headless emulator on this runner never surfaced a real IME under bounded automation, even after switching soft keyboards and restarting the emulator without snapshots. The committed IME probe now skips rather than hanging the suite or fabricating proof.
137+
- `LocalClipboardManager` deprecation warnings remain outside this polish slice.
138+
- No push performed.
139+
- No PR opened.

apps/android/app/build.gradle.kts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@ dependencies {
5050
implementation("androidx.lifecycle:lifecycle-runtime-ktx:2.9.0")
5151
implementation("com.google.firebase:firebase-messaging")
5252
implementation("com.squareup.okhttp3:okhttp:4.12.0")
53+
implementation("org.commonmark:commonmark:0.29.0")
5354
implementation("org.jetbrains.kotlinx:kotlinx-coroutines-android:1.10.2")
5455
implementation("org.jetbrains.kotlinx:kotlinx-serialization-json:1.8.1")
5556

0 commit comments

Comments
 (0)