TASK-60: one owner for the transition
Two writers own one geometry — the rail's pose and ZoneOverview's scale, running opposite curves off the same progress. Three attempts to make the numbers agree failed in a session. The strand proves it: the repro path is card taps, which never reach the rail's clear-the-pose code. Plan follows quickstep, which is on this machine: one shift 0..1, the live window transformed onto the real card rect, end targets as an enum with LAST_TASK a destination rather than an abandon branch, drag length derived from that rect. The transition is a verb because she gives the tour, under the origin rules input.rs already enforces: agent input is not evidence and the lock surface takes fingers only.
This commit is contained in:
parent
528d290ba6
commit
ee8697cd8f
1 changed files with 114 additions and 4 deletions
|
|
@ -1,8 +1,110 @@
|
|||
# TASK 60 — multitasking is a place, not a transition
|
||||
|
||||
**Status: 2026-08-07 — the cards draw.** Zone cards with live previews, a close
|
||||
control and a zone label, verified on hardware. What remains is the swipe
|
||||
*into* it, which is still awkward.
|
||||
**Status: 2026-08-07 (later) — the cards draw, and the transition is being
|
||||
rebuilt around one owner.** Patching the two geometries into agreement failed
|
||||
three times in one session; the plan below replaces them with one. Read
|
||||
"One owner" before touching any of it.
|
||||
|
||||
## One owner — the rebuild, 2026-08-07
|
||||
|
||||
### The fault, stated once
|
||||
|
||||
**Two writers own one geometry.** The rail scales the real windows through
|
||||
`pose`; `ZoneOverview` scales its cards through `scale`. Both read
|
||||
`zonePullProgress`, and a session was spent trying to make the two numbers
|
||||
agree — the card ran `0.6 → 1.0` while the pose ran `1.0 → 0.6`, so at the
|
||||
handoff the window was at 0.6 of the glass and the card arrived near full
|
||||
bleed.
|
||||
|
||||
That is `DEVICE-STATE-MACHINE.md` §1's blind actors in the render path, and
|
||||
TASK-52 names the same rule for exactly this reason: *one attention model, one
|
||||
clock, effects as strategies over it*. Every symptom is the one fault — the
|
||||
size pop, the doubled frame (viewtop's 3 px `#9EC7FF` under the card's
|
||||
`radius: 18`), and the strand.
|
||||
|
||||
**The strand is the proof.** Casey, 2026-08-07: open btop, swipe to
|
||||
multitasking, tap Home, reopen multitasking, tap btop — btop comes back as a
|
||||
small card in the middle of the screen. Every clear-the-pose path built that
|
||||
day hangs off the rail's drag edge (`endPull` → `clearPose`). *Those taps are
|
||||
`ZoneOverview`'s and never touch the rail*, so nothing ever runs. A transform
|
||||
that one surface applies and a different surface must remember to undo will
|
||||
always have a path that forgets. Note also that `pose` is TASK-52 **#10,
|
||||
gravity wells** — an atmosphere primitive that navigation borrowed.
|
||||
|
||||
### What the prior art does — quickstep, on this machine
|
||||
|
||||
`~/Downloads/lineage-trebuchet/quickstep/src/com/android/quickstep/`.
|
||||
|
||||
- **One float.** `SwipeUpAnimationLogic.mCurrentShift` ∈ [0,1] — its own comment:
|
||||
0 = preview snapshot completely visible, 1 = *"preview snapshot completely
|
||||
aligned with the recents view"*. `TaskViewSimulator` transforms the **live
|
||||
window onto the real card rect**. The card never has to be made to match the
|
||||
window, because the window is placed on the card. There is no second geometry.
|
||||
- **The drag length is derived from the destination.**
|
||||
`getSwipeUpDestinationAndLength(dp, ctx, TEMP_RECT, …)` returns the rect and
|
||||
the length together, and `mDragLengthFactor = dp.heightPx / mTransitionDragLength`.
|
||||
Our `missionAt` is 18% of the panel, a number with no relationship to where
|
||||
the card actually is.
|
||||
- **End targets are an enum**, not a set of booleans: `HOME, RECENTS, NEW_TASK,
|
||||
LAST_TASK, ALL_APPS` (`GestureState.java:77`). Every gesture resolves to
|
||||
exactly one, and **`LAST_TASK` is a first-class destination** — "went back to
|
||||
the app" is a real endpoint that animates, not an abandon branch.
|
||||
- **The controller owns the transform and hands it back at the endpoint.**
|
||||
Nothing hopefully-undoes anything, which is structurally why Android cannot
|
||||
strand a window and we can.
|
||||
- **Dwell is first-class.** `isFling = mGestureStarted && !mIsMotionPaused &&
|
||||
|endVelocity| > threshold`, and in gestural mode `mIsMotionPaused → RECENTS`
|
||||
(`AbsSwipeUpHandler:1121,1322`). A pause is never a fling.
|
||||
`MIN_PROGRESS_FOR_OVERVIEW = 0.7`.
|
||||
|
||||
Sailfish/Glacier (`~/phone-qml-research/glacier-home`) is the QML-side reference
|
||||
for the same shape and is worth reading before the shell half.
|
||||
|
||||
### The plan
|
||||
|
||||
1. **One owner of the geometry.** The compositor owns the transition: one verb
|
||||
carrying `shift` 0→1, where 1 means the window sits exactly on its card rect.
|
||||
The destination rect is named once at gesture start, not re-derived per
|
||||
frame. The shell stops calling `poseActiveZone` for navigation and stops
|
||||
scaling cards; `ZoneOverview` draws chrome — label, close control,
|
||||
neighbours — and never a competing transform.
|
||||
2. **End targets as an enum.** One end-target state replaces
|
||||
`missionControlOpen` / `overviewOpen` / `zonePullProgress`. Entering and
|
||||
leaving become the same machinery whether the gesture came from the pill or
|
||||
from a card tap — which is precisely what the strand repro broke. `LastTask`
|
||||
is a destination, so the transform is released by *arriving*, not by
|
||||
remembering to clear.
|
||||
3. **Detents from the destination rect**, not 18%. Keep the dwell; make
|
||||
"paused is never a fling" explicit rather than emergent.
|
||||
4. **One frame.** A window inside the transition is furniture in the overview's
|
||||
composition, so `focus_border` suppresses itself while a window is owned by
|
||||
the transition and the card carries the chrome.
|
||||
|
||||
### It has to be a verb, because she gives the tour
|
||||
|
||||
Casey, 2026-08-07: there is a point where an agent is asked for a tour or a demo
|
||||
of the phone, *"and that does mean even these little gesture steps will be
|
||||
possible."* So the transition is a **verb with a caller**, not a side effect of a
|
||||
touch handler — `shift` and the end target are both reachable from the verb
|
||||
table, or a tour is impossible and TASK-30's third capability enumeration grows
|
||||
a fourth.
|
||||
|
||||
The principles that already govern her hand govern this too, and they are built
|
||||
(`input.rs`):
|
||||
|
||||
- `Origin::{Physical, Agent}`, carried from the source, never a caller-set field.
|
||||
- `AGENT_SLOT_BASE = 1 << 16`, so a synthesized contact cannot land on a slot a
|
||||
thumb owns.
|
||||
- `Origin::is_evidence()` — **an agent-driven tour must not be evidence.** A demo
|
||||
that raises `observed_confidence` or feeds the idle budget is the machine
|
||||
believing a human is present because she moved a window.
|
||||
- Step-up stays human-only, and already is: `input.rs:432` routes
|
||||
`Origin::Physical => Route::LockSurface` and `Origin::Agent =>
|
||||
Route::Withheld("the lock surface takes fingers, not the agent")`. The
|
||||
navigation verb must not become a way around that.
|
||||
|
||||
Connects to TASK-50 (the same origin machinery, and the inverse mapping `pose`
|
||||
owes the hit test) and doctrine §13 (the 60 is hers; the credential is the 40).
|
||||
|
||||
## 2026-08-07 — the cards were zero pixels wide
|
||||
|
||||
|
|
@ -185,8 +287,16 @@ changes whether cards need to be drag targets.
|
|||
Open an app, immediately open multitasking: the new app is there.
|
||||
- Tapping a card goes to that zone. Home is reachable from it.
|
||||
- Whatever drives the transition and whatever draws the view agree — no frame
|
||||
where a window is scaled by one and laid out by the other.
|
||||
where a window is scaled by one and laid out by the other. Met by there being
|
||||
one geometry, not by two that were tuned to match.
|
||||
- The scale-on-drag either continues into the view or is gone. Not both.
|
||||
- **The strand repro passes.** btop → multitasking → Home → multitasking → tap
|
||||
btop, and btop is full size. No path leaves a window transformed, including
|
||||
the ones that never touch the rail.
|
||||
- **The gesture is reachable as a verb.** An agent can drive `shift` and pick an
|
||||
end target well enough to demo multitasking, and the run leaves
|
||||
`Origin::Agent` throughout: no evidence, no idle-budget credit, no route to
|
||||
the lock surface.
|
||||
|
||||
## Connects to
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue