You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
One surface for capture and ask. The existing capture screen gains an ask mode — same screen, same composer, no second route. Capture stays the default on every launch.
Supersedes #321, which drifted toward a separate /ask screen. There is no separate screen.
Why now
Mobile implements one of the four verbs. api.ask() landed in #330 but nothing calls it — a user can put memories in from their phone and ask nothing of them. Recall works end-to-end on the API and in Admin; this is purely the missing mobile surface.
Design constraints (learned the hard way — do not rediscover)
The vertical axis is taken.apps/mobile/app/index.tsx drives BOTH hold-to-talk and slide-up-to-type from a single vertical Pan (beginHold, slidingRef, dragY). Mode switching MUST be horizontal, with activeOffsetX set so a mostly-vertical drag never switches mode and a mostly-horizontal one never starts a recording. This is not theoretical: adb vertical swipes during testing repeatedly started voice recordings instead of opening the composer, and the emulator has no mic so it wedged (pcm_writei failed flooding logcat).
One composer, two intents. Reuse the existing text input rather than building a second one. The mode changes the placeholder, the submit action, and what renders below — not the input itself.
Capture is the default, always. Do not persist the last mode. Capturing is reflexive; asking is deliberate. A user who opens the app to dump a thought must never land in ask mode.
A grounded miss is not an error. The server returns 200 with an empty citations array and floored confidence when nothing clears the §05.6 miss band (documented at api.ask in src/lib/api.ts). Render it as a calm "nothing on this yet" — visually distinct from the failure state, which is reserved for a thrown ApiError.
How to do it
Mode state in index.tsx; horizontal Pan (or Gesture.Race with the existing one) with a clear activation threshold.
A visible, non-chrome mode indicator consistent with the monochrome ui-spec (Part 1A) — one field, white ink, no second palette.
Goal
One surface for capture and ask. The existing capture screen gains an ask mode — same screen, same composer, no second route. Capture stays the default on every launch.
Supersedes #321, which drifted toward a separate
/askscreen. There is no separate screen.Why now
Mobile implements one of the four verbs.
api.ask()landed in #330 but nothing calls it — a user can put memories in from their phone and ask nothing of them. Recall works end-to-end on the API and in Admin; this is purely the missing mobile surface.Design constraints (learned the hard way — do not rediscover)
The vertical axis is taken.
apps/mobile/app/index.tsxdrives BOTH hold-to-talk and slide-up-to-type from a single verticalPan(beginHold,slidingRef,dragY). Mode switching MUST be horizontal, withactiveOffsetXset so a mostly-vertical drag never switches mode and a mostly-horizontal one never starts a recording. This is not theoretical: adb vertical swipes during testing repeatedly started voice recordings instead of opening the composer, and the emulator has no mic so it wedged (pcm_writei failedflooding logcat).One composer, two intents. Reuse the existing text input rather than building a second one. The mode changes the placeholder, the submit action, and what renders below — not the input itself.
Capture is the default, always. Do not persist the last mode. Capturing is reflexive; asking is deliberate. A user who opens the app to dump a thought must never land in ask mode.
A grounded miss is not an error. The server returns 200 with an empty
citationsarray and floored confidence when nothing clears the §05.6 miss band (documented atapi.askinsrc/lib/api.ts). Render it as a calm "nothing on this yet" — visually distinct from the failure state, which is reserved for a thrownApiError.How to do it
index.tsx; horizontalPan(orGesture.Racewith the existing one) with a clear activation threshold.api.ask(), which already inherits fix(mobile): refresh the expired session instead of losing the capture #318's one-shot refresh-and-retry, so a question asked long after sign-in re-authenticates instead of being lost.Out of scope
Acceptance criteria
POST /memory/askand renders the answer with its citations, on the same screen.