tasks: 30 agent reach, 31 radial dial, 32 pill+keyboard; 08 gains the two unsurfaced findings
This commit is contained in:
parent
9590e74bd9
commit
3e4373bbc5
5 changed files with 251 additions and 1 deletions
|
|
@ -93,6 +93,27 @@ Wants (from handoff doc item 12):
|
|||
race the idle lock again.
|
||||
- The conclusions want to land in `power-profiles-daemon` as the hint layer.
|
||||
|
||||
## Two things the machine knows and nothing says (open, 2026-07-26)
|
||||
|
||||
**(f) `sensors_degraded` reaches no surface.** Source health landed
|
||||
(`DEVICE-STATE-MACHINE.md` §10): a source that reported and went silent for 90 s
|
||||
is `down`, not quiet, and every forensic snapshot carries `sensors_degraded`.
|
||||
The trail knows. No screen does. The crash reporter structurally cannot help —
|
||||
all three of its sources key on something *failing*, and the SLPI outage exited
|
||||
status 0 (archive/05). This is the surfacing half: an ambient indicator when a
|
||||
source that used to work has stopped, legible on the lock surface, saying which
|
||||
and since when. `device_state` already ships `sensor_health` over IPC.
|
||||
|
||||
**(g) The confidence gates are computed, logged, and never branched on.** §4's
|
||||
threshold table (<0.3 / 0.3–0.6 / 0.6–0.8 / >0.8) and the cross-sensor
|
||||
disagreement rules are written to the trail and ignored. **This needs a decision
|
||||
before code**, and the decision moved on 2026-07-26: the table was written when
|
||||
proximity suppressed DPMS wake and blanked locked screens, and proximity now
|
||||
does neither — it vetoes tap-to-wake and is otherwise evidence. So the question
|
||||
is no longer "what should confidence gate" but "is anything left for it to
|
||||
gate". The honest candidate is the doze promotion rate and possibly nothing
|
||||
else. Answer that, then wire it or delete the table and record why.
|
||||
|
||||
## Sub-tasks (do separately)
|
||||
|
||||
1. State machine + pub/sub (mce/datapipe shape), device-flag gating.
|
||||
|
|
|
|||
72
docs/tasks/30-agent-reach-verb-tables.md
Normal file
72
docs/tasks/30-agent-reach-verb-tables.md
Normal file
|
|
@ -0,0 +1,72 @@
|
|||
# TASK 30 — Agent reach: verb tables across the surfaces
|
||||
|
||||
**Status:** half built 2026-07-26 (sessiond). **Size:** one session per surface.
|
||||
**Repo:** `~/Projects/souveraine` (`surfaces/quickshell`).
|
||||
|
||||
## Goal
|
||||
|
||||
The agent owns the device 60/40 (doctrine §13) and cannot currently compose a
|
||||
single intent across two surfaces. sessiond can now be enumerated and its
|
||||
refusals branched on; the shell's surfaces cannot. Until they can, "full phone
|
||||
control" is control of the device and not of the things on it.
|
||||
|
||||
## What exists after 2026-07-26
|
||||
|
||||
sessiond has the pattern, working, in `src/sessiond/protocol.rs`:
|
||||
|
||||
- `describe` returns a verb table — every op, whether it mutates, the refusal
|
||||
codes it can return, and a request line that parses. Knowing an op exists is
|
||||
not enough to call it; a test round-trips every advertised example through
|
||||
the real parser, so a table that lies fails the build.
|
||||
- Refusals carry a code beside the prose: `unsupported_op`,
|
||||
`invalid_argument`, `refused_by_state`, `not_permitted`, `unavailable`.
|
||||
Not-now, never, and wrong-arguments are three different next moves.
|
||||
- Requests carry an optional `intent`, stamped onto every trail entry the
|
||||
request produces, so a chain's leaves join back to one decision.
|
||||
|
||||
## What to build
|
||||
|
||||
The same three things on each shell surface, in this order — smallest blast
|
||||
radius first, which is the order the dock manifest work already argued for:
|
||||
|
||||
1. **`dock.*`** — the manifest exists; give it `describe` and coded refusals.
|
||||
2. **`apps.*`** — `app-inventory-manifest.md` (archive/from-substrate) scoped
|
||||
the inventory; it is a read surface, so it is the cheapest to make legible.
|
||||
3. **`shell.*`** — surfaces and state.
|
||||
4. **`settings.*`** — the largest, and the one with a real policy layer:
|
||||
`SETTINGS-AUTHORITY.md` already specifies risk tiers and propose-vs-set.
|
||||
Its refusals map onto the same five codes; do not invent a sixth.
|
||||
|
||||
Quickshell drops `var` returns, so every result is a JSON string. That bug cost
|
||||
the `{ok, reason}` contract its first six months — every new surface inherits
|
||||
the convention or it cannot be chained.
|
||||
|
||||
## Then: chaining itself
|
||||
|
||||
With the vocabulary in place, what remains is failure semantics. A chain that
|
||||
refuses at step three is not the same as one that never started, and whether
|
||||
the earlier steps roll back is per-chain and must be **stated, not
|
||||
discovered**. Decide it when the first real chain exists, not before.
|
||||
|
||||
## Acceptance
|
||||
|
||||
- `describe` on every surface, with examples that parse, enforced by a test.
|
||||
- Every refusal carries a code from the five; none carries only prose.
|
||||
- A chain of four verbs across two surfaces records one intent in the trail,
|
||||
and reconstruction reads the decision rather than four orphans.
|
||||
- A refusal mid-chain is legible enough for the agent to pick another path
|
||||
without being told what went wrong out of band.
|
||||
|
||||
## Do not
|
||||
|
||||
- Build a new toolcall integration. Settled 2026-07-13: the agent reaches
|
||||
these through its existing harness.
|
||||
- Let a surface invent its own refusal vocabulary.
|
||||
- Inline the teaching. The surface exposes; the Souveraine School teaches.
|
||||
|
||||
## Connects to
|
||||
|
||||
`SESSION-AUTHORITY-DOCTRINE` §13 (the mandate), `SHELL-ECOSYSTEM.md`
|
||||
(manifests + guarded methods), `FIRST-CLASS-APPS.md` §6/§7 (legibility and
|
||||
agency are two of the nine), `SETTINGS-AUTHORITY.md`, TASK-31 (the dial is the
|
||||
human rendering of the same vocabulary).
|
||||
74
docs/tasks/31-radial-dial.md
Normal file
74
docs/tasks/31-radial-dial.md
Normal file
|
|
@ -0,0 +1,74 @@
|
|||
# TASK 31 — The radial dial
|
||||
|
||||
**Status:** open, wanted soon (Casey, 2026-07-26). **Size:** component first,
|
||||
then invocations, then contents. **Repo:** `~/Projects/souveraine`
|
||||
(`surfaces/quickshell`).
|
||||
|
||||
## Goal
|
||||
|
||||
A radial dial of options, summoned by a gesture, reachable by thumb without
|
||||
looking. The phone's fastest path from "I want a thing" to the thing.
|
||||
|
||||
## The idea worth getting right first
|
||||
|
||||
**The dial and the agent's verb table are the same vocabulary.** One rendered
|
||||
for a thumb, one for a composer. A dial whose entries are a hand-written list
|
||||
is a third place device capabilities are enumerated — after the verb table and
|
||||
the manifests — and it will drift from both within a month.
|
||||
|
||||
So the dial's contents come from the surfaces' `describe` (TASK-30): each entry
|
||||
is a verb that mutates, is permitted in the current state, and has somewhere to
|
||||
say what it does. A verb the agent cannot reach should not appear on the dial
|
||||
either, and vice versa. That is the check that keeps them one system.
|
||||
|
||||
This also settles what happens on a refused entry: the dial shows the refusal's
|
||||
*code* as its disabled reason (`refused_by_state` → "not while locked"),
|
||||
because the surface already had to say so.
|
||||
|
||||
## Priority order — the component before the contents
|
||||
|
||||
TASK-18 learned this the hard way and wrote it down: *"the stevia keyboard
|
||||
shipped glitchy because the surface work was rushed."* A dial whose actions are
|
||||
stubs is fine. A janky dial is not.
|
||||
|
||||
1. **The component.** Geometry, anchor, open/close animation, thumb reach,
|
||||
what happens when it opens near a screen edge, how it dismisses. Built from
|
||||
Souveraine-owned AGPL primitives — this is a first user of the primitive set
|
||||
`souveraine-lock-primitives` (archive/from-substrate) specifies, and a good
|
||||
reason to build them, since a dial needs shapes and ripples that ii's
|
||||
widgets would otherwise supply.
|
||||
2. **Invocation.** Squeeze is the natural one (TASK-13) and is not the only
|
||||
one — long-press and an edge gesture want to reach it too. Every path
|
||||
registers through the gesture/keyboard routing system, never a hardcoded
|
||||
binding (INTERFACE-ARCHITECTURE §4).
|
||||
3. **Contents.** From the verb tables, per above.
|
||||
|
||||
## Constraints inherited, not invented
|
||||
|
||||
- **Layer and state.** The dial declares its layer and lets shell state gate
|
||||
it (`FIRST-CLASS-APPS` §4). It must not paint over a locked screen, fight the
|
||||
OSK, or survive an overview.
|
||||
- **Lock and tier.** Ambient entries may appear on the lock surface; personal
|
||||
ones and any mutation gate on `screenLockSecure` plus a fresh grant
|
||||
(`FIRST-CLASS-APPS` §5). A dial is exactly the shape of thing that leaks by
|
||||
being convenient.
|
||||
- **Update management.** It ships as part of the shell surfaces, which are
|
||||
**not packaged today** — they live in `$HOME` and arrive by rsync. TASK-25
|
||||
names this; the dial does not get an exception, and "how does this reach a
|
||||
device" is part of its acceptance, not an afterthought.
|
||||
|
||||
## Acceptance
|
||||
|
||||
- Opens under the thumb from any app, at any screen edge, without clipping.
|
||||
- Dismisses by the same gesture, by tapping away, and by pressing back.
|
||||
- Entries are derived from a surface's verb table, not a list in the QML.
|
||||
- A disabled entry says why, in the words the refusal already used.
|
||||
- Does not appear over a locked screen with anything personal on it.
|
||||
- Reaches a device by a mechanism that survives the next update.
|
||||
|
||||
## Connects to
|
||||
|
||||
TASK-13 (squeeze — the first invocation), TASK-30 (the vocabulary),
|
||||
TASK-18 (selection menu — the other summoned surface; they should not become
|
||||
two frameworks), `FIRST-CLASS-APPS.md`, `INTERFACE-ARCHITECTURE.md` §4,
|
||||
`souveraine-lock-primitives.md` (the owned widget set this needs).
|
||||
80
docs/tasks/32-pill-and-osk-as-apps.md
Normal file
80
docs/tasks/32-pill-and-osk-as-apps.md
Normal file
|
|
@ -0,0 +1,80 @@
|
|||
# TASK 32 — The pill and the keyboard, as owned apps
|
||||
|
||||
**Status:** open. Both are erroneous in daily use (Casey, 2026-07-26).
|
||||
**Size:** two sessions, one each. **Repo:** `~/Projects/souveraine`,
|
||||
`~/Projects/Pixel3Arch/pkgs/stevia`.
|
||||
|
||||
## Why one task for two surfaces
|
||||
|
||||
They fail the same way and neither has an owner. Each is a thing the user
|
||||
touches constantly, each was built by patching symptoms, and neither has a
|
||||
section that says how it ships or who decides its behaviour.
|
||||
`FIRST-CLASS-APPS.md` lists nine requirements; both fail §1, §6, §7 and §8, and
|
||||
the keyboard has failed §8 hardest — four pkgrels of it existed only on the
|
||||
phone before any of it came back to the repo.
|
||||
|
||||
Treat each as an app: what it is, what it owns, how it is configured, **how it
|
||||
updates**, and what it refuses. Not a bag of fixes.
|
||||
|
||||
## The keyboard
|
||||
|
||||
**Current state:** stevia 0.56.0-7, patched for Hyprland, with a dictation mic
|
||||
key. TASK-24 scoped the layout rework and it has not happened: backspace is on
|
||||
the wrong row, the bottom row has seven keys against the reference's six, and
|
||||
the layout matches no validated design. TASK-17 records the other live defect —
|
||||
completion is on by default but stevia asks hunspell for `en-us` while the
|
||||
dictionary is `en_US`, so it may still show nothing.
|
||||
|
||||
**The rule TASK-24 already wrote and that must hold:** start from a validated
|
||||
reference (squeekboard `us+apple`, gmankab `us-mobile`), not from first
|
||||
principles. No layout change ships without a screenshot of the rendered
|
||||
keyboard on the device.
|
||||
|
||||
**Update management.** stevia is a Pixel3Arch package built on archdev and
|
||||
hand-carried; nothing publishes it (TASK-27). Upstream ALARM ships a
|
||||
`squeekboard` that declares `conflicts=stevia`, so the phone currently pins
|
||||
squeekboard to keep both — an interim recorded in `rootfs-overlay/etc/
|
||||
pacman.conf` that must come off when our own squeekboard ships at a version
|
||||
outranking theirs. The osk-switch toggle is the runtime arbiter and is staged,
|
||||
not functional.
|
||||
|
||||
## The pill
|
||||
|
||||
**Current state:** `SystemGestureRail`, always-on overlay, one MouseArea
|
||||
recognising double-tap, swipe-up and swipe-down. The interaction layer is
|
||||
sound. What is missing is ownership: the pill's z-order guarantee was
|
||||
documented but not enforced until a layerrule was added, the OSK lift was a
|
||||
stale hardcoded 315 px that stacked it over the keys, and single-tap-as-Home is
|
||||
specified in TASK-14 but lives nowhere as a contract.
|
||||
|
||||
**What it should own:** the gesture vocabulary and nothing else. It forwards to
|
||||
named IPC targets and makes no app decisions (INTERFACE-ARCHITECTURE §1).
|
||||
Every new gesture is a row in the table, not a branch inline — and with
|
||||
TASK-31, one of those rows is the radial dial.
|
||||
|
||||
**Update management.** Ships with the shell surfaces, which are unpackaged and
|
||||
live in `$HOME`. Same gap as everything else in `surfaces/quickshell`; TASK-25
|
||||
owns the fix.
|
||||
|
||||
## Acceptance
|
||||
|
||||
- Each has a section in `docs/` naming what it owns, what it refuses, and how
|
||||
it reaches a device — not a list of fixed bugs.
|
||||
- Keyboard: layout matches a validated reference, screenshot-verified at every
|
||||
level; completion actually completes.
|
||||
- Pill: the gesture table is single-sourced; adding a gesture touches one row.
|
||||
- Both ship by a mechanism that survives an update, or the gap is named with
|
||||
the task that owns it.
|
||||
|
||||
## Do not
|
||||
|
||||
- Patch another keyboard symptom without a reference layout in hand.
|
||||
- Add pill gestures while z-order is enforced by documentation rather than by
|
||||
a rule.
|
||||
|
||||
## Connects to
|
||||
|
||||
TASK-17, TASK-24 (the keyboard's history — read both before touching a
|
||||
layout), TASK-14 (single-tap Home), TASK-31 (the dial is a pill gesture),
|
||||
TASK-25/27 (how either of them ships), `FIRST-CLASS-APPS.md`,
|
||||
`INTERFACE-ARCHITECTURE.md`.
|
||||
|
|
@ -15,7 +15,7 @@ plus open threads from the 2026-07-17 session.
|
|||
| 2 | [Lockscreen-as-Rust-system: glance + swipe](02-lockscreen-rust-system.md) | in progress | stopgap shipped 2026-07-17 |
|
||||
| 3 | [Boot timing: fade splash → lock, no extra fixes](03-boot-timing-splash-to-lock.md) | diagnosed | EBUSY handoff race is the last timing bug; splash text killed, holder added |
|
||||
| 7 | [WCD9340 mic: functional-pinned; unpin + fidelity](07-mic-wcd9340-slim-tx.md) | functional 07-20 | defect: power pin; kernel `mic-race-fix` |
|
||||
| 8 | [Device state manager / power profiles](08-device-state-manager.md) | actuating 07-25 | clock + actuators; lock-before-blank is an invariant and hypridle's listeners are deleted; (b) charge real, (c)(d) open, **(e) lease still missing — a shell deploy over a locked session still crashes the lockscreen** |
|
||||
| 8 | [Device state manager / power profiles](08-device-state-manager.md) | actuating 07-25 | clock + actuators; lock-before-blank is an invariant and hypridle's listeners are deleted; (b) charge real, (c)(d) open, **(e) lease still missing**, **(f) `sensors_degraded` reaches no surface**, **(g) the confidence gates need a decision before code** |
|
||||
| 9 | [Suspend-resume FTS calibration race](09-suspend-resume-fts.md) | interim-fix | kernel-side; cold-boot only |
|
||||
| 12 | [Face auth as a capability factor (Gaze reference)](12-gaze-reference-face-auth.md) | open | per-target: phone needs front-cam bring-up |
|
||||
| 13 | [Active Edge (squeeze) as a sensor input](13-active-edge-squeeze.md) | open | substrate up; bring-up unit not drafted |
|
||||
|
|
@ -33,6 +33,9 @@ plus open threads from the 2026-07-17 session.
|
|||
| 27 | [Gitea pipeline audit](27-gitea-pipeline-audit.md) | open | overlay is not a package; no `primary` branch; poisoned build sysroot |
|
||||
| 28 | [Handover on upgrade](28-upgrade-handover.md) | open | half-upgrades move authority silently; blocked-by TASK-27 packaging |
|
||||
| 29 | [SouveraineOS Updater](29-souveraine-updater.md) | started 07-25 | rust rewrite of pachub; doesn't build yet; first repo to build *into* the pipeline |
|
||||
| 30 | [Agent reach: verb tables across the surfaces](30-agent-reach-verb-tables.md) | half built 07-26 | sessiond has describe + refusal codes + intent; dock/apps/shell/settings do not |
|
||||
| 31 | [The radial dial](31-radial-dial.md) | open | component before contents; entries come from the verb tables, not a list in QML |
|
||||
| 32 | [The pill and the keyboard, as owned apps](32-pill-and-osk-as-apps.md) | open | both erroneous daily; neither has an owner or a shipping story |
|
||||
| — | [Unify the shell trees](unify-shell-trees-laptop-phone.md) | open | ~900-file `ii` drift; blocks durable shell fixes reaching the phone |
|
||||
|
||||
Archived (see `archive/`): 05 crash reporter — done 2026-07-21,
|
||||
|
|
|
|||
Loading…
Reference in a new issue