App clients reach minerva only over HTTPS now: the Android cleartext
policy blocks plain HTTP to minerva.lan, and the public Let's Encrypt
cert on app.doctate.de chains to the system trust store, so no
network-security-config change is needed. Update the profile template's
SERVER_URL and comment to reflect the HTTPS convention.
closes#7
The ALLOWED_SERIALS guard matched the adb transport serial, which over
WiFi is a rotating ip:port (changes on every wireless-debugging restart)
and over USB is the bare hardware serial. Pinning the transport serial
meant every port rotation broke the deploy until the profile was hand-edited.
Resolve the device's stable ro.serialno (getprop) after target resolution
and match that against ALLOWED_SERIALS instead. The transport serial still
drives adb/gradle/ANDROID_SERIAL; only the wrong-watch guard switches to the
stable identity, so it survives port rotation and is identical over WiFi/USB.
Also: 'devices' now prints 'transport -> ro.serialno' per device to make the
value for ALLOWED_SERIALS easy to read off. Help text and the example profile
are updated to the ro.serialno form.
closes#6
Small red 'DEV' tag in the top-right of CaseListScreen and RecordingScreen
when BuildConfig.IS_DEV_PROFILE is true. Production profiles render
nothing — Krey's UI stays clean.
refs #3
Dev profiles (name ends in -dev) get 'Doctate (Dev)' in the launcher;
production profiles keep the plain 'Doctate'. The string resource
@string/app_name is no longer the application-level label, only used
for the complication entry where the launcher distinction is irrelevant.
refs #3
BuildConfig now carries the active profile name plus an isDev boolean
(profile name ends in '-dev'). The manifestPlaceholder 'appLabel'
switches between 'Doctate' and 'Doctate (Dev)' for the launcher.
refs #3
Profile file (via -Pdoctate.* injected by run.sh) is now the only source.
local.properties stays gitignored but is no longer consulted by the build.
refs #3
./run.sh watch <profile> <subcmd> [args]
The second positional after \`watch\` is now the profile name. apply_target
calls load_profile + verify_serial_allowed before Gradle, so a wrong-watch
install refuses fast without burning a build. DOCTATE_API_KEY pass-through
is gone — keys come from the profile file only.
refs #3
Helpers source profiles.d/<name>.sh and assert SERVER_URL, API_KEY, and
ALLOWED_SERIALS. verify_serial_allowed dies with an explicit cross-watch
warning when the attached serial is not in the profile's allow-list. Not
yet wired into apply_target — that follows in the next commit.
refs #3
Adds the directory, gitignore rule, and checked-in template. Real profile
files (e.g. brummel-dev.sh) live alongside but are gitignored as they
contain plaintext api_keys.
refs #3
Treat every non-Success upload response as Transient so audio survives
expired sessions, 4xx replies, and unparseable 2xx bodies — the watch
keeps retrying instead of silently dropping the recording. Drop the
UploadResult.Terminal variant entirely and the SyncWorkerLoop branch
that consumed it.
Also reap orphaned unsynced markers on app start: a syncedToServer=false
marker without a matching pending pair (audio gone) and older than a
5-minute grace window is inconsistent — the user couldn't discard it,
and no other path could clean it up. Eliminates the 2026-05-03 21:08
ghost-marker class.
Test fixture (InMemoryCaseStore), SyncWorkerLoopTest, UploadClientTest,
and StartupCleanupTest updated to reflect the new contract.
Add Fachrichtung to prompt and refine medical terms.
Added Fachrichtung to the system prompt, instructing the LLM to consider
the medical specialty for precise terminology.
Also, added "Abdomensonographie" to the `medical_terms.txt` file.
The tile layout has been refactored to display a list of recent cases
instead of the currently active case. This change includes:
- Removing the "current case" view and its associated logic.
- Implementing a new `caseListContent` function to render a list of up
to 8 recent cases.
- Modifying the main `buildTileLayout` to integrate the new case list
and a prominent "Neu" (New) button.
- Updating the styling and click handling to reflect the new layout and
functionality.
Use the current case's oneliner text as the title for the remote input
intent. This ensures consistency with the CaseListScreen's display when
no oneliner is present, showing a "…" placeholder. This improves the
user experience by making the system input picker's title match what the
user just selected.
Increase `max_completion_tokens` for `gpt_oss_120b` from 8192 to 16384
to prevent incomplete responses.
Navigate to the detail screen before the recording screen when starting
a new case, ensuring correct back navigation.
Replace stale references in 17 Kotlin files:
- doctate-client-core::* -> doctate-desktop::*
- doctate-client-core/src/* -> clients/desktop/src/*
- doctate-common/src/* -> common/src/*
The doctate-common:: crate path stays valid (crate name unchanged).
PendingStoreTest.kt is in src/test/, so the test mirror is also
updated.
Verification:
- grep for "doctate-client-core" / "doctate-common/src/" in
clients/wearos/ returns 0 hits.
- gradlew :app:testDebugUnitTest BUILD SUCCESSFUL (23s) -- also
retroactively confirms stage-2's directory move did not break
any Gradle relative-path assumptions.
- cargo clippy --all-targets -- -D warnings clean in both
server/ and clients/desktop/ workspaces.
This concludes the four-stage server-vs-clients build-world split:
- stage 1 (39cc666): dissolve doctate-client-core
- stage 2 (0c66fc6): rename to common/, clients/desktop, clients/wearos
- stage 3 (7b4fe87): split into standalone workspaces
- stage 4 (this): update wearos anchors
docs/projektplan.md to be updated separately.
Move three directories into their target topology:
- doctate-common/ -> common/
- client-desktop/ -> clients/desktop/
- watch/wearos/ -> clients/wearos/
Update doctate-common path-dependency in 3 Cargo.toml files
(server, clients/desktop, experiments) and the workspace
members list in the root Cargo.toml. Crate names unchanged
(doctate-server, doctate-common, doctate-desktop).
Workspace still in single-Cargo.lock form; isolation into
standalone workspaces follows in stage 3. All 508 tests pass,
experiments standalone-workspace also resolves the new path.