docs(meditate): ADR 0038, D15, dreams spoken, as the developer asked

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: Tizian 「ティツィアーン」 <raisondetredev@pm.me>
This commit is contained in:
Tizian 「ティツィアーン」 2026-11-03 14:47:52 +01:00
commit 76846244ca
Signed by: raisondetredev
GPG key ID: 07F6FCF405488B64

View file

@ -170,6 +170,39 @@ names and pictures are its own). Everything below is Halkyon's own.
- **Profile's Practice** shows, once the journal holds a dream, a small *Dream
journal* card: the dreams of this month and the lucid ones of all.
- Not done: reminders to write (D12), dreams linked to sittings, figures over time.
- **D15 Dreams spoken** (3 Nov 2026, the developer's request): speech-to-text in the
journal's editor, as Learn's assistant field takes questions spoken (Halkyon Learn's
ADR 0021, D67: the device's own speech recognition, `speech_to_text`). The agent's
recommendations, to be confirmed:
- **Shared, not copied**: Learn's `SpeechInput` and `DeviceSpeechInput` move into
halkyon_app with their fake, Learn importing them from there unchanged; beside them
`Dictation`, generic, which writes what is heard where the cursor stands (in place
of a selection, set apart by a space on either side where the text has none) and
shows the words so far. Learn's button stays Learn's: it sends, and replaces from
where it started. Todo and Train link the plugin now but declare no microphone, so
nothing there listens.
- **In the editor**: a microphone under the text, where the device recognises speech
(none on Linux, as Learn's); listening, it turns into Stop with "Listening…" and the
words heard beside it. It listens in the app's language, else the device's own.
- **A dream is longer than a question: it restarts by itself** while the button stays
on, rather than offering to continue: half awake, a tap after every pause would
interrupt the telling, and the button says throughout that it listens. Each listen
may pause 30 s and last 10 minutes (Apple's recogniser stops sooner, Android's after
a few seconds' silence whatever is asked), and after three listens running hear
nothing it stops by itself, so a phone left on the table doesn't listen on.
- **Privacy**: on Android Meditate asks for recognition on the device
(`DeviceSpeechInput(preferOnDevice: true)`: Android 12's on-device recogniser where
the language is installed, else the recogniser with *prefer offline*); should that
fail before a word is heard, it listens as Android otherwise does from then on, which
may send the sound to Google or the phone's maker. Apple's and Windows' recognisers
choose for themselves (the plugin's on-device flag on Apple fails outright where
unsupported, so it isn't asked). The instance never hears it. The privacy page says
so where Meditate's server serves it (`privacyPagePoints` in `meditate_base.dart`,
with what Meditate keeps sealed), as Learn's does.
- **Today's card** offers *Speak it* beside it, opening a new dream already listening.
- The platforms declare it as Learn's do: `RECORD_AUDIO` and the recognition service's
query on Android, the microphone's and speech recognition's usage texts on iOS and
macOS, and macOS's `audio-input` entitlement.
## Steps
@ -181,7 +214,8 @@ names and pictures are its own). Everything below is Halkyon's own.
sitting's screen (D6), Explore (D10).
4. **Today and Profile** (3 Nov): D8, D9.
5. **The dream journal** (3 Nov): D14, the `dream` table and its migration, the Journal
tab, a dream's screen, Today's card, Settings' *Journal*, Profile's figures.
tab, a dream's screen, Today's card, Settings' *Journal*, Profile's figures; and
dreams spoken (D15).
6. **Released and deployed** (later, as Todo's step 5): `apps/meditate/release.dart`, a key
of its own, the F-Droid listing, a snap, `deploy/compose.meditate.yaml` at
meditate.halkyon.eu (its `.env` values the developer has set already, 2 Nov), its