The developer asked for Train to offer what Learn's Settings offer first
(ADR 0014's amendment of 4 Nov 2026). Train passed a fixed look, the
system's theme and language; it now opens halkyon_app's LookCubit on
<app support>/look.json in main, provides it above InstanceGate, and its
start screens and each person's MaterialApp follow it. Settings show
DeviceLookCard right after the Sync and operator's cards, as Learn's,
offering English (UK), English (US) and Deutsch (trainLanguages).
The app's tests tapping Delete account and About now scroll them into
view first (tapInSettings, as Todo's and Meditate's): the card moved
them below the phone's fold.
Whats-New: Settings: choose the app's appearance and language.
Whats-New-De: Einstellungen: Darstellung und Sprache der App wählen.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: Tizian 「ティツィアーン」 <raisondetredev@pm.me>
The developer asked for Todo to offer what Learn's Settings offer first
(ADR 0014's amendment of 4 Nov 2026). Todo passed a fixed look, the
system's theme and language; it now opens halkyon_app's LookCubit on
<app support>/look.json in main, provides it above InstanceGate, and its
start screens and each person's MaterialApp follow it. Settings show
DeviceLookCard right after the Sync and operator's cards, as Learn's,
offering English (UK), English (US) and Deutsch (todoLanguages).
Whats-New: Settings: choose the app's appearance and language.
Whats-New-De: Einstellungen: Darstellung und Sprache der App wählen.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: Tizian 「ティツィアーン」 <raisondetredev@pm.me>
The developer asked for Todo, Train and Meditate to offer Learn's
Appearance and Language (ADR 0014's amendment of 4 Nov 2026). Their
model, store, cubit and card move into halkyon_app: Appearance and Look
(a BCP 47 tag, null for the device's language), FileLookStore keeping it
in the app's support folder as JSON written by rename (per device, not
synced, read before the first frame), LookCubit for the apps to provide
above InstanceGate, and LookSettingsCard / DeviceLookCard with the texts
moved from Learn's arbs (look*, the same words). Each app passes the
languages it speaks, named in their own language.
Learn keeps its stored choice where it was, among its DeviceSettings,
and feeds the shared card from them: no migration, so nobody's language
or appearance moves, and nothing changes on its screen.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: Tizian 「ティツィアーン」 <raisondetredev@pm.me>
The developer's review of 4 Nov 2026. "Japanese on this device" becomes
"Dictionaries on this device", with one row a language: its name at the
start, what the device holds or that the download failed beneath it, and
its action at the end (Download with its size, the progress, Remove),
built as a list of rows so Korean's and Chinese's line up beneath
later. Japanese's is the only one now. The help speaks of a language's
dictionaries in general, then of what Japanese's hold (MeCab's, JMdict).
Whats-New: Settings lists the dictionaries on this device by language, each with its own Download or Remove.
Whats-New-De: Die Einstellungen listen die Wörterbücher auf diesem Gerät nach Sprache, jede mit eigenem Herunterladen oder Entfernen.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: Tizian 「ティツィアーン」 <raisondetredev@pm.me>
Arranging Home kept no order of its own: a drop showed the old order
until the layout saved came back through the settings, once the
dashboard's changes settled 300 ms later, so the widget snapped back and
then jumped. _Arranging now holds the layout as arranged, shows each
change at once and saves it behind, taking a layout from the settings
only once its own changes are back (or, with none pending, as changed
on another device). The handle was an IconButton with an empty
onPressed inside the drag listener, whose tap and tooltip competed with
the drag; it is a plain icon now, named for screen readers.
Whats-New: Arranging Home's widgets, a widget stays where you drop it, and dragging starts at once.
Whats-New-De: Beim Anordnen der Widgets auf der Startseite bleibt ein Widget, wo du es ablegst, und das Ziehen beginnt sofort.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: Tizian 「ティツィアーン」 <raisondetredev@pm.me>
The developer's review of 4 Nov 2026. The entry goes from a studyset's
Add material, and with it the sheet for pasting a text
(proposeCardsFromText, _TextSheet), its three texts and proposeCards'
fromStudyset, which only it set to false. A note's and a PDF page's
flashcards stay; their tests now drive the proposals sheet from a note.
Whats-New: Add material no longer offers Flashcards from a text; a note's or a PDF page's flashcards stay.
Whats-New-De: Material hinzufügen bietet keine Karteikarten aus einem Text mehr an; die aus einer Notiz oder einer PDF-Seite bleiben.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: Tizian 「ティツィアーン」 <raisondetredev@pm.me>
Inside a studyset the field flickered as it opened and closed: the
floating location switched between a raised centre and the centre,
which Scaffold animates by scaling the button out and in. It keeps one
location now, raised above the licence line by padding. While open it
no longer slides away as the studyset or the Library scrolls
(ScrollHidingFab.pinned, new), and the keyboard covers Home, the
Library, a studyset and a session rather than shrinking them; the field
lifts itself by as much of the keyboard as reaches above it.
NavigationFrame no longer resizes for the keyboard itself, leaving it
to each tab's own scaffold, which still does by default (Todo's,
Train's and Meditate's tests pass unchanged).
Whats-New: Inside a studyset, the question field opens without flickering, stays while you scroll, and the screen no longer jumps when the keyboard comes.
Whats-New-De: In einem Lernset öffnet sich das Fragefeld ohne Flackern, bleibt beim Scrollen stehen, und der Bildschirm springt nicht mehr, wenn die Tastatur kommt.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: Tizian 「ティツィアーン」 <raisondetredev@pm.me>
Each screen's button kept its own open state and its own draft, so the
question half written on the Library was gone on Home. ComposerCubit,
provided beside ConversationDockCubit, now holds whether the field is
open and the draft (text, files attached, parts chosen) for every
button. Switching tabs keeps it as it is (AppShell says so before
goBranch); going to another screen within a tab, or over the tabs, keeps
it open only while something is written or attached. Only the button of
the screen at the router's location unfolds, so no tab kept alive
behind holds a second field.
Whats-New: The question you are writing stays open as you switch tabs.
Whats-New-De: Die Frage, die du schreibst, bleibt offen, wenn du den Tab wechselst.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: Tizian 「ティツィアーン」 <raisondetredev@pm.me>
The developer's review of 4 Nov 2026. Below the question, × and + stand
at the start, who answers is centred and the conversations and the
microphone stand at the end, every button the same rounded square, the
microphone listening and Send too. The row above the text ("Only what I
choose · 2 parts") goes, as +'s sheet offers the same choice; a web
search gets + with that row alone. Who answers shows its model's name
alone ('Haiku 4.5', AssistantProvider.modelName: Anthropic's without
"Claude", others as they are), outlined in its provider's colour (D60).
The microphone is halkyon_app's Dictation: what is said goes where the
cursor stands, and it listens again after each pause until stopped. It
gives way to Send once anything could be sent, as Claude's field does.
Whats-New: The question's buttons are in one row: close and + on the left, who answers in the middle, Conversations and the microphone on the right.
Whats-New: What goes along is chosen under +, for the web search too.
Whats-New: Who answers shows the model's name, in its provider's colour.
Whats-New: The microphone keeps listening after a pause, writing where the cursor is, until you stop it.
Whats-New-De: Die Knöpfe der Frage stehen in einer Reihe: Schließen und + links, wer antwortet in der Mitte, Unterhaltungen und Mikrofon rechts.
Whats-New-De: Was mitgeht, wählst du unter +, auch für die Websuche.
Whats-New-De: Wer antwortet, zeigt den Namen des Modells, in der Farbe seines Anbieters.
Whats-New-De: Das Mikrofon hört nach einer Pause weiter zu und schreibt, wo der Cursor steht, bis du es stoppst.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: Tizian 「ティツィアーン」 <raisondetredev@pm.me>
On GrapheneOS, which installs no recogniser, the microphone did nothing
and stayed listening: speech_to_text's initialize throws a
PlatformException (recognizerNotAvailable) there rather than answering
false, and DeviceSpeechInput let it through. A listen now answers how it
went (SpeechStart: listening, noRecognizer, unavailable) and never
throws; Learn's field and Meditate's dream say that no speech
recognition is installed and name two to install (FUTO Voice Input,
Google's speech services), in halkyon_app's texts. It also passes
androidNoBluetooth, as the apps declare no Bluetooth permission the
plugin would otherwise ask for.
Whats-New: Where the device has no speech recognition, the microphone says so and how to get one.
Whats-New-De: Wo das Gerät keine Spracherkennung hat, sagt das Mikrofon das und wie du eine bekommst.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: Tizian 「ティツィアーン」 <raisondetredev@pm.me>
The developer's review of 4 Nov 2026: "an actual conversation with the AI
chatbot is not desirable and necessary". The field's voice-mode button,
the screen it opened, reading answers aloud and its texts go, and with
them flutter_tts, its patched copy in third_party/ (one override fewer),
the TTS_SERVICE query in the manifest and the plugin's registrants. The
microphone stays and dictates into the question. ImageApproval is the
conversation sheet's own again, as only voice mode needed it.
Whats-New: Voice mode is gone; the microphone dictates into your question.
Whats-New-De: Der Sprachmodus ist weg; das Mikrofon diktiert in deine Frage.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: Tizian 「ティツィアーン」 <raisondetredev@pm.me>
The title's placeholder in quick add and in a task's sheet read "What's
to be done?"; the developer asked for Todoist's plainer "Task name"
("Aufgabenname").
Whats-New: A task's title field now says "Task name".
Whats-New-De: Das Titelfeld einer Aufgabe zeigt jetzt „Aufgabenname“.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: Tizian 「ティツィアーン」 <raisondetredev@pm.me>
Adding or editing a project was a dialog of a name and a colour. It is
now a screen of its own on a phone (a dialog where sheets are dialogs),
as Todoist's Add project: the name counted to 120, a description, the
colour, the parent project, a Favourite switch and the layout, Display's
pictures. All of it lives in the project's sealed payload, the schema
still 1, no server model or migration; the payload now keeps fields it
doesn't know, as a task's does.
A new project starts with the layout picked, and Display's Reset all
returns to that default rather than to List. Browse lists sub-projects
indented and folding under their parents, and the favourites in a group
above; a project is never offered as its own ancestor, and a parent's
deletion takes its sub-projects, naming them first, as Todoist's. ADR
0033, D28.
Whats-New: Add project and Edit project are a screen of their own, with a description, a parent project, Favourite and the layout.
Whats-New: Browse lists sub-projects under their parents and your favourite projects at the top.
Whats-New: Reset all in Display returns to the layout the project was made with.
Whats-New-De: „Projekt hinzufügen“ und „Projekt bearbeiten“ sind eine eigene Seite, mit Beschreibung, übergeordnetem Projekt, Favorit und Layout.
Whats-New-De: „Übersicht“ zeigt Unterprojekte unter ihren Projekten und deine Favoriten oben.
Whats-New-De: „Alles zurücksetzen“ in der Anzeige kehrt zum Layout zurück, mit dem das Projekt angelegt wurde.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: Tizian 「ティツィアーン」 <raisondetredev@pm.me>
F-Droid's Time is for clocks and timers; a to-do list with a calendar
belongs under Task and Calendar & Agenda, the developer's choice of
both. No other app used Time, so the repository no longer lists it. The
release test now checks every category the listing names. ADR 0033 gets
D26 (the review's fixes so far) and D27.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: Tizian 「ティツィアーン」 <raisondetredev@pm.me>
A sub-task tapped in a task's sheet opened a sheet of its own over it,
so Grocery List > Dairy > Milk stacked three. It now takes the sheet's
place, as the steps of the sheet's path already did (TaskTile's onOpen),
and the sheet keeps the tasks it showed: the system's back returns to
the last. Back is caught with a BackButtonListener, not a PopScope,
which would also hold back a tap beside the sheet, a swipe and Escape:
those close the sheet whole. A picker open over the sheet is closed by
back first.
Whats-New: A sub-task opens in its task's sheet instead of over it; back returns to the task.
Whats-New-De: Eine Unteraufgabe öffnet sich im Blatt ihrer Aufgabe statt darüber; Zurück führt zur Aufgabe.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: Tizian 「ティツィアーン」 <raisondetredev@pm.me>
The round check sat in the middle of the row, so on a row with a
description, a date or a long title it stood below the title. As
Todoist's it now stands by the title's first line. ListTile centres its
leading or tops it at its padding, never at the title's line, so the
check and the texts share the tile's title, the texts lowered by half
of what the check's 48 dp tap target is taller than a line (computed
from the text scale, the tap target kept).
Whats-New: A task's circle stands beside the first line of its title.
Whats-New-De: Der Kreis einer Aufgabe steht neben der ersten Zeile ihres Titels.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: Tizian 「ティツィアーン」 <raisondetredev@pm.me>
As Todoist's, Today's app bar says how many tasks it holds, those
overdue and those due today together ("3 tasks"). TabScreen takes an
optional subtitle for it, left out while tasks are being chosen, when
the title counts those instead.
Whats-New: Today says how many tasks are overdue or due today under its title.
Whats-New-De: „Heute“ zeigt unter dem Titel, wie viele Aufgaben überfällig oder heute fällig sind.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: Tizian 「ティツィアーン」 <raisondetredev@pm.me>
Edit project built the project anew from its name, colour and position,
so saving it reset its Display (layout, grouping, sorting, filters) to
the first one. It now changes the name and colour of the project as it
is.
Whats-New: Editing a project no longer resets its Display.
Whats-New-De: Ein Projekt zu bearbeiten setzt seine Anzeige nicht mehr zurück.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: Tizian 「ティツィアーン」 <raisondetredev@pm.me>
The date sheet returned a date only from its days and No date: a time or
a duration picked and the sheet then closed by its X, a swipe or a tap
beside it gave nothing back, so the task kept no time. The sheet now
keeps the date the time makes as it is picked, on the task's day or
today where it had none (as Todoist), and pickTaskDate returns it when
the sheet closes without a choice. Quick add uses the same sheet.
Whats-New: A time picked for a task's date is kept, however you close the Date sheet.
Whats-New-De: Eine Uhrzeit für das Datum einer Aufgabe bleibt, wie auch immer du das Blatt „Datum“ schließt.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: Tizian 「ティツィアーン」 <raisondetredev@pm.me>
The skin temperature's line ran backwards in places: the band's samples
aren't always in time order, and neither the Loop's lines, nor the kept
day, nor the chart sorted them. They are sorted now, a time given twice
kept once, as the lines are read and as a kept day is opened, and
WorkoutChart draws any points in the order of their x, from the least
to the most.
The heart rate spiked down: the band writes 0 where it lost contact,
and each run's mean, the chart's one point a run, counted those in. A
value that isn't a heart's rate is 0, none read, in its place (so the
samples after keep their times), left out of every mean, days kept
before included; the chart draws the samples a point a minute, averaged
across runs, rather than one mean a run, which zigzagged where runs lay
close. ADR 0030, D65.
Whats-New: A day's skin temperature no longer runs backwards, and its heart rate no longer drops where the band lost contact.
Whats-New-De: Die Hauttemperatur eines Tages läuft nicht mehr rückwärts, und sein Puls fällt nicht mehr ab, wo das Band den Kontakt verlor.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: Tizian 「ティツィアーン」 <raisondetredev@pm.me>
The maps follow the theme where the source names a dark style, which
only the instance's own map did: OpenFreeMap, the default source, had
none, so a dark phone showed Liberty's bright map. The default now
hands OpenFreeMap's Dark style beside Liberty, and an operator setting
MAP_STYLE_URL may set MAP_DARK_STYLE_URL (HTTPS, else none) beside it,
passed on by compose.train.yaml and named in .env.example.
ADR 0030, D65.
Whats-New: The map is dark in a dark theme.
Whats-New-De: Die Karte ist im dunklen Design dunkel.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: Tizian 「ティツィアーン」 <raisondetredev@pm.me>
As Strava's: over the last 6 % below the highest the sheet goes, its
top corners square off from 28 to 0 and its handle folds away, so the
bar above, opaque by then, meets it without the map showing through
the corners. The bar names the activity rather than the workout, whose
name already heads the sheet: it was in sight twice. sheetSquared in
track_camera.dart, tested beside barShown. ADR 0030, D65.
Whats-New: A workout's page pulled all the way up meets the bar square, which names the activity.
Whats-New-De: Ganz hochgezogen schließt die Seite eines Trainings eckig an die Leiste an, die die Sportart nennt.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: Tizian 「ティツィアーン」 <raisondetredev@pm.me>
The segmented choice of Music, Metronome and Off sat in the music
tile's subtitle, beside its icon, where a phone of 360 dp wrapped
"Metronome" into "Metronom/e". It takes the list's whole width now,
under its title, each label on one line and scaled down where larger
text still leaves too little room. ADR 0030, D65.
Whats-New: The Record sheet's Music, Metronome and Off each fit on one line.
Whats-New-De: Musik, Metronom und Aus passen im Aufzeichnen-Blatt jeweils auf eine Zeile.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: Tizian 「ティツィアーン」 <raisondetredev@pm.me>
On a fresh install (GrapheneOS) a walk recorded no GPS on the screen,
which waited for GPS throughout though the file was whole. The app
listens to the recorder's lines as soon as it asked for the start, and
Android starts the service a moment later: listening first, it got
nothing of the file, and the service then wrote the header straight to
the file, past what hands each line on. The reader takes the first line
it gets as the header, found none, and dropped every line after.
The service now writes its header through write() as every line, and
the app takes the header from the file's first line where lines came
without one (RecordingReader.recover, on the next second), reading the
lines kept since after it, so either order and either recorder version
is followed. The fake recorder can now begin late, as the service does.
On foot, auto-pause by steps paused after 5 s and went on only with a
step where the phone has no step detector or one switched off
(GrapheneOS' Sensors): GPS speed decides there, and until the first
step and once the detector has been silent 30 s. A minute without any
fix, the recording screen asks whether location is on and precise.
ADR 0030, D65.
Whats-New: A recording follows its GPS again on a phone where it waited for GPS throughout.
Whats-New: Auto-pause on foot goes by GPS speed where the phone counts no steps.
Whats-New: After a minute without GPS, the recording screen asks whether location is on and precise.
Whats-New-De: Eine Aufzeichnung folgt ihrem GPS wieder auf Handys, auf denen sie die ganze Zeit auf GPS wartete.
Whats-New-De: Die automatische Pause zu Fuß richtet sich nach der GPS-Geschwindigkeit, wo das Handy keine Schritte zählt.
Whats-New-De: Nach einer Minute ohne GPS fragt die Aufzeichnung, ob der Standort an und genau ist.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: Tizian 「ティツィアーン」 <raisondetredev@pm.me>
AppRefreshIndicator ticks (selectionClick, as a choice on the floating bar
or the rail) once the pull commits: as it snaps back to refresh, or as it
refreshes at once, whichever comes first, and not for a pull let go too
early. Train's list of days pulled to read the band used Flutter's own
RefreshIndicator, the older spinner; it takes the app's now, and the tick
with it.
Whats-New: Pulling a list down to refresh ticks lightly.
Whats-New-De: Eine Liste zum Aktualisieren herunterziehen gibt ein leichtes Tippen.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: Tizian 「ティツィアーン」 <raisondetredev@pm.me>
The drafts came from the commits' subjects, which are written for
developers: each of the releases of 4 Nov 2026 (Todo 0.2.0, Train 0.3.0,
Learn 0.24.0) listed every commit since the last, Meditate's among them
where it touched a shared package, more than twice F-Droid's 500
characters, the German all still to translate, and each had to be written
again whole.
A commit people would notice now says so in its message's trailers,
`Whats-New: <sentence>` once a change and `Whats-New-De: <Satz>` in the
same order, and the draft is those lines alone, the features' first, a
missing translation marked TRANSLATE:. Only where no commit of the
release carries one does it fall back to the subjects. A commit whose
scope names apps (feat(todo,meditate): ...) counts for those alone, any
other for every app it touches. Over a running next.<language>.txt per
app, which parallel branches conflict on at every merge, and over an
assistant drafting at release time (a key, the commits sent to a
provider, a different text each run). ADR 0030, D61.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: Tizian 「ティツィアーン」 <raisondetredev@pm.me>
Only the deploy builds the images, on the server, after every check
has passed, so an image that pub refuses cost a push each time (twice
on 4 Nov 2026). A step of tool/check.dart, right after the packages,
replays each Dockerfile's build stage up to its `dart pub get` from
the working tree's files in an empty folder, with Dart alone at the
image's version (downloaded once into ~/.cache/halkyon-check/, its
SHA-256 checked), offline, in an environment holding nothing of the
machine's Dart or Flutter: `dart run` from Flutter sets DART_ROOT,
through which pub found Flutter and accepted what the image refuses.
Checked on both failed deploys' states, which fail it as they did,
and on the fix, which passes. --images-only runs it alone, in
seconds. The list of images, dartImages, moves into
tool/src/images.dart, and a test keeps every Dockerfile building with
Dart on it.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: Tizian 「ティツィアーン」 <raisondetredev@pm.me>
Two deploys failed building the images (4 Nov 2026): first the
dictionaries' image lacked third_party/ (pub refuses an override whose
path is missing, exit 66), then, with it copied, pub refused the
overrides themselves, as the three plugins depend on the Flutter SDK,
which the dart image doesn't have (exit 69); every image would have.
No image's package uses them, so tool/workspace_only.sh, which already
narrows the root pubspec for an image, drops the overrides naming
third_party/, and no Dockerfile copies it.
Each image's build stage replayed from this commit with a standalone
Dart 3.13.4, a fresh pub cache, dash and mawk: all four build, and the
commit deployed before fails as the deploy did.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: Tizian 「ティツィアーン」 <raisondetredev@pm.me>
The deploy of 55c73a7e failed building it: the root's dependency
overrides name the three patched plugins by path, and pub refuses a
path that isn't there (exit 66), though the curator uses none of them.
The servers' Dockerfiles got the copy with the overrides; the
curator's was missed. Checked by running each image's steps up to
`dart pub get` in an empty folder: the curator's failed as on the
server before, and all four images resolve now.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: Tizian 「ティツィアーン」 <raisondetredev@pm.me>
Two app tests failed before noon: from 4 to 12 o'clock Today's card for
last night's dream pushes the cards below it down, and its list hadn't
built Recently sat yet, which ensureVisible needs. They now scroll the
list until the card is built (scrollToday), whatever the hour.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: Tizian 「ティツィアーン」 <raisondetredev@pm.me>
AGP 9 compiles Kotlin itself (android.builtInKotlin=true in every app),
and warns that applying the Kotlin Gradle Plugin will soon fail.
flutter_web_auth_2 5.1.0, keyboard_height_plugin 0.3.0 and flutter_tts
4.2.5 still apply it unconditionally, so their pub releases are copied
into third_party/ with only their android/build.gradle changed, and
the root overrides them by path (third_party/README.md says when to
drop each). The servers' images copy third_party/, as pub refuses an
override whose path is missing. third_party/ isn't our own code: left
out of the analysis and the format check.
All four apps' APKs build without the warning. A Kotlin daemon's
session file that slipped into Train's android/ goes, and every app's
android/.gitignore keeps .kotlin/ out.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: Tizian 「ティツィアーン」 <raisondetredev@pm.me>
Every weight is still kept in kilograms. It is shown and entered in the
person's unit, chosen in Your body (Weight in: kg | lb, the profile's
new weightUnit), else the region's: pounds in the US, Liberia and
Myanmar. The entry takes 44 to 880 lb, the same 20 to 400 kg. A weight
left untouched in Your body is saved exactly as it was, not rounded
through pounds. The other figures stay metric.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: Tizian 「ティツィアーン」 <raisondetredev@pm.me>
Three forks of the 3 Nov review each wrote the same widget (Todo's and
Meditate's TitleWithHelp, Train's HelpTitle); halkyon_ui's ExplainedTitle,
from Learn's, takes their place.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: Tizian 「ティツィアーン」 <raisondetredev@pm.me>
What a switch or a section explains, rather than what is the person's
own, is one tap away: `HelpTitle`, a tile's title with halkyon_ui's
`HelpButton` beside it, in place of the explaining subtitles of Moving
more's reminders and suggestions, the music's playlists and smaller
copies, and the Loop's detection, firmware check and firmware through
the instance. Health Connect's short hints stay (they name what each
switch does, and its "taken back" state takes their place), as do its
rationale, the Loop's warnings before an update or a reset and the
settings' one-line hints.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: Tizian 「ティツィアーン」 <raisondetredev@pm.me>
A person's weights are each a sealed `body_weight` row, as the days and
the places: the weight in grams, when it was measured (UTC), where it
came from and, for Health Connect's, the record's id and app are the
payload; the server sees the space and the ciphertext alone.
Progress gets a Weight card after Your body: the latest and its day,
its line over time (held, each weight and its day), the plus to enter
one (a comma taken as a point, 20 to 400 kg, when measured, today by
default) and All, the list to delete one. The latest weight is also
Your body's, which the band's and the zones' figures work from. In
kilograms alone: Train is metric throughout and has no units setting
yet.
Health Connect's weight records are read in when switched on in its
screen (READ_WEIGHT, asked as the others): each record once, its id kept
in health_connect.json also after it is deleted here, never Train's own,
and none within 10 minutes and 0.1 kg of a weight entered in Train.
The migration (20261103204323683-body-weights):
- creates (or replaces, unchanged) `gen_random_uuid_v7()`, the
default of every UUID id, as each of Serverpod's migrations does;
- CREATE TABLE "body_weight": "id" uuid primary key defaulting to a
UUID v7, "spaceId" bigint (the sync space), "keyId" text (the key
that sealed it), "payload" bytea NOT NULL (the sealed content),
"nonce" bytea;
- CREATE INDEX "body_weight_space_idx" on "spaceId", for a space's
rows as the sync reads them;
- a foreign key from "spaceId" to "offline_sync_spaces"("id"),
ON DELETE CASCADE, so that an account's deletion takes its weights
with its space;
- the version rows of Train's and every module's migrations.
Nothing existing changes, so nothing is lost.
Tests: the row written and read back in its owner's space, and the
denials: another person reads none of them, and writing one into
another's space throws OfflineSyncSpaceMembershipException and leaves
it empty; an account's deletion takes them.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: Tizian 「ティツィアーン」 <raisondetredev@pm.me>
WorkoutChart, the line of every chart in Train (a day's heart rate and skin
temperature, a workout's, a route's height): held, a line marks the point
nearest the finger and follows it as it moves, its value beside the title,
with its moment where the chart says how to write it (a day's heart rate:
the time of day). A tap does nothing; lifting the finger clears it (the
developer's review of 3 Nov 2026, as stock charts do).
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: Tizian 「ティツィアーン」 <raisondetredev@pm.me>
The night's chart threw mid-paint where Polar's last phase starts at the
night's end or after it: its right edge was clamped between left + 1 and
the row's width, the lower bound then above the upper (an ArgumentError).
A throw mid-paint leaves the canvas moved, so the rows below and the charts
after them were drawn out of place, the skin temperature's among them. Each
phase now stays within its row, a pixel wide at least.
Nightly Recharge showed Polar's marks for a figure it has none of (-1 for
the recovery and the intervals, -100 for the nervous system's status, 0 for
a baseline not yet learnt) as the person's own. Recharge.known leaves them
out, on the page and in the days' list; the figures are rows, each with the
person's usual below it, and Polar's explanation of them (the status from
-10 to +10, what each measures) is behind halkyon_ui's question mark.
The page is a screen of its own over the tabs, without the bar and with the
way back at its top left, its parts in cards (the developer's review of
3 Nov 2026; D60 had it inside Profile).
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: Tizian 「ティツィアーン」 <raisondetredev@pm.me>
As Learn's and Todo's: halkyon_app's Sync card first in Settings, and the
dot on the cog while sync fails; the person's SyncService is now part of
TrainPerson, which was the only reason Train had neither (the developer's
review of 3 Nov 2026).
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: Tizian 「ティツィアーン」 <raisondetredev@pm.me>
The developer's review of 3 Nov 2026 (ADR 0033, D25): an explanation stands
one tap away, behind halkyon_ui's HelpButton beside the setting's name,
rather than always below it. Todo: resetting sub-tasks, the automatic
reminder (its value stays below), counting a recurrence from completion.
Meditate: keeping the screen on, the streak, the morning's dream prompt.
What is the person's own (a value, a count) stays in view; an empty list's
message and quick add's hint about highlighted words, shown only while
there are some, stay too.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: Tizian 「ティツィアーン」 <raisondetredev@pm.me>
The developer's review of 3 Nov 2026 (ADR 0033, D24): on a phone the sheet
opens as high as its content, at most 65 % of the window, the list above it
in view, and is dragged up to the whole window or down to close; its title,
description, date and reminders each in a rounded box, its priority, labels,
deadline and project as a row of chips (named "Priority", "Labels",
"Deadline" while unset), and its sub-tasks in a box ending in Add sub-task.
Where sheets are dialogs, and in the pane beside the list, the same parts.
Todo keeps no comments, so the sheet has no comment field.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: Tizian 「ティツィアーン」 <raisondetredev@pm.me>
The developer's review of 3 Nov 2026 (ADR 0033, D23): in place of the tall
sheet with its title and Add button, a rounded bar just above the keyboard,
the list still in view behind a lighter barrier: the title, then a row of
boxed buttons (+ for the description and the deadline, the date, the
priority, the labels, the project), each its icon alone until something is
set, and a send button. Its buttons show from the start rather than once
typing begins (D15 had them come with the first letter). Where sheets are
dialogs, the same bar in a dialog.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: Tizian 「ティツィアーン」 <raisondetredev@pm.me>