detached 9c5858a

docs(architecture): describe live picker and preview streams

commit
9c5858aba462696fc37579d2cf4130df79fff3a3
author
brice · · 2026-09-22 21:17 UTC
parent
5e20063
signature
GPG VerifiedCD88F9E564E0102646FB6077A1A07C7C7C3E349D · arch-gpg Verified for the committer email
1 file · +9 -9
M docs/architecture.md +9 -9
@@ -38,8 +38,8 @@ Every result retains the request ID for strict correlation. Version negotiation
3838 broker codec over `wire.ScanEnvelope`, the broker preamble (roles 3/4,
3939 exact `protocol.Version`, 1 MiB..16 MiB / 1..64 KiB ceilings, 4 KiB
4040 byte-length bound), multipart snapshot assembly, per-connection operation
41- and stream trackers, and the bounded admission lock. It is not activated
42- by production composition until P3.2.
41+ and stream trackers, and the bounded admission lock. Production clients
42+ use this codec through the broker IPC adapter.
4343 - `internal/adapters/brokeripc`: the Plan 001 P3.3 private local broker
4444 endpoint. It implements `ports.BrokerListener` (accepting same-user clients
4545 and running one brokerwire session per accepted connection) and
@@ -49,8 +49,8 @@ Every result retains the request ID for strict correlation. Version negotiation
4949 same-user `SO_PEERCRED` admission, race-safe stale-socket recovery,
5050 foreign-path refusal) and the shared `streamframe` framing. It owns the
5151 bounded per-connection queues, the snapshot publisher, the per-stream typed
52- bridge over `sessionwire`, and deterministic disconnect cleanup. Like P3.1 and
53- P3.2 it is not activated by production composition.
52+ bridge over `sessionwire`, and deterministic disconnect cleanup. Production
53+ clients connect through this endpoint.
5454 - `internal/adapters/quic`: one-stream QUIC carriage (TLS 1.3, epoch ALPN,
5555 exact SHA-256 pin, single bidirectional stream, bounded admission) plus
5656 the short-lived SSH bootstrap (ephemeral certificate, 32-byte token,
@@ -98,13 +98,13 @@ Interactive observation is a separate opt-in composition. `term.Terminal` remain
9898
9999 A client publishes exactly one of three presentations at a time. `picker` is the local picker: the client is usable and describable without a broker and without a daemon. `connecting` is an attachment attempt that has not committed its first frame. `attached` is a committed attachment, and only it carries the validated session identity, the committed output boundary, and the real actionable generation; `picker` and `connecting` carry the run's stable service handle and their status with every session field zeroed, so a capture can never present session metadata as an attachment and no caller can fence an input action against a generation no attachment committed. The former `detached`, `reconnecting`, and `transitioning` values are removed without alias: a reconnect is `connecting`, a detach returns to `picker`, and terminating closes the UI service instead of becoming a fourth persistent presentation. The presentation is published inside the terminal's UI output transaction by its owner: the supervisor publishes `connecting` before the attachment foreground is granted and `picker` after the run drained and revoked, while the admitted foreground publishes `attached` only after its first frame was written, flushed, and committed.
100100
101-Session navigation is an autonomous client presentation, not an attachment interaction. While attached, Alt+Space opens the daemon command palette; `SSP` / `session-picker` ends the current attachment with `Detached{Reason: ReasonDetachToPicker}`. The session stays headless. The attachment worker maps this to `AttachmentDetachToPicker` settlement; the supervisor drains and revokes the foreground before giving its input lease and terminal writer to the local picker. Search, sorting, cursor movement, selection, and broker-backed attachment opening are client-owned. No picker bytes or navigation selections are sent to the serving daemon.
101+Session navigation is client-owned. While attached, Alt+Space opens the daemon command palette; `SSP` / `session-picker` opens the client picker as an overlay over the live attachment. Cancel returns to the same attachment without reconnecting. Committing a different destination switches attachments through `connecting`; attachment loss or explicit detach leaves the picker as the standalone presentation. Search, sorting, cursor movement, selection, and broker-backed attachment opening are client-owned. Daemon move-destination offers still use the attached worker's separate move picker.
102102
103-The selected row owns one client-scoped live preview subscription through `ports.BrokerService`. The broker opens sequential observation streams over its existing local or remote physical pool, sends bounded `RemotePreviewRequest` values, and publishes the newest fenced result. Cursor movement and resize replace the subscription with a strictly newer generation; broker loss, commit, picker close, and client exit cancel it. The client accepts a publication only when broker epoch, connection, generation, target, and dimensions still match, so a late capture cannot repaint another selection. Preview cells remain bounded, memory-only, and are never persisted or logged.
103+The selected row owns one client-scoped live preview subscription through `ports.BrokerService`. The broker opens one long-lived observation stream over its local or remote physical pool; the daemon pushes changed `RemotePreview` frames at a broker-selected interval (33 ms local, 125 ms remote). Cursor changes are debounced for 80 ms, and the client retains eight recent previews so a selection can remain visible while refreshing. Broker loss, commit, picker close, and client exit cancel the watch. The client checks epoch, connection, generation, target, and dimensions before painting; previews remain bounded, memory-only, and are never persisted.
104104
105-There is no forwarding or compatibility path through `PickerOffer`. The daemon does not dispatch `client picker request` or `picker control request`, cannot open a navigation interaction, and cannot resolve a `PickerActionNavigate` or `PickerActionKill` interaction selection.
105+The daemon does not own the session picker or resolve cross-daemon navigation; it can offer a move-destination picker to the attached client and receives its typed selection or close reply.
106106
107-Pane/tab move destination pickers are not forwarded through session navigation. The existing daemon interaction remains temporarily available only to the daemon command palette; it captures and revalidates the move source and accepts only move intents. The autonomous attachment worker does not consume that interaction. Explicit scripted move commands remain available. The command palette itself remains daemon-owned and is separate from session-picker presentation.
107+Pane/tab move destination pickers are separate from session navigation. The daemon captures and revalidates the move source; the attached worker displays the offer and sends the selected move target back. The command palette remains daemon-owned.
108108
109109 ### Resize repaint fence
110110
@@ -112,7 +112,7 @@ A terminal resize reaches the client as one coalesced invalidation owned by the
112112
113113 ### Attention and notifications
114114
115-Attention remains a daemon fact. The autonomous picker renders catalogue facts obtained through the broker; it does not subscribe to an attachment's legacy picker interaction. Legacy move-destination interactions retain their own attention refresh machinery.
115+Attention remains a daemon fact. The broker publishes it from fresh observations but strips it from durable snapshots. The client's route ledger forwards attention order to the serving daemon for status-bar bells and cross-daemon jump-to-attention; the picker displays session and tab bells. The serving daemon uses that same route snapshot to display remote palette destinations, without monitoring other daemons.
116116
117117 ## Broker-owned hosts and daemon composition
118118
@@ -38,8 +38,8 @@ Every result retains the request ID for strict correlation. Version negotiation
38 broker codec over `wire.ScanEnvelope`, the broker preamble (roles 3/4,38 broker codec over `wire.ScanEnvelope`, the broker preamble (roles 3/4,
39 exact `protocol.Version`, 1 MiB..16 MiB / 1..64 KiB ceilings, 4 KiB39 exact `protocol.Version`, 1 MiB..16 MiB / 1..64 KiB ceilings, 4 KiB
40 byte-length bound), multipart snapshot assembly, per-connection operation40 byte-length bound), multipart snapshot assembly, per-connection operation
41- and stream trackers, and the bounded admission lock. It is not activated41+ and stream trackers, and the bounded admission lock. Production clients
42- by production composition until P3.2.42+ use this codec through the broker IPC adapter.
43 - `internal/adapters/brokeripc`: the Plan 001 P3.3 private local broker43 - `internal/adapters/brokeripc`: the Plan 001 P3.3 private local broker
44 endpoint. It implements `ports.BrokerListener` (accepting same-user clients44 endpoint. It implements `ports.BrokerListener` (accepting same-user clients
45 and running one brokerwire session per accepted connection) and45 and running one brokerwire session per accepted connection) and
@@ -49,8 +49,8 @@ Every result retains the request ID for strict correlation. Version negotiation
49 same-user `SO_PEERCRED` admission, race-safe stale-socket recovery,49 same-user `SO_PEERCRED` admission, race-safe stale-socket recovery,
50 foreign-path refusal) and the shared `streamframe` framing. It owns the50 foreign-path refusal) and the shared `streamframe` framing. It owns the
51 bounded per-connection queues, the snapshot publisher, the per-stream typed51 bounded per-connection queues, the snapshot publisher, the per-stream typed
52- bridge over `sessionwire`, and deterministic disconnect cleanup. Like P3.1 and52+ bridge over `sessionwire`, and deterministic disconnect cleanup. Production
53- P3.2 it is not activated by production composition.53+ clients connect through this endpoint.
54 - `internal/adapters/quic`: one-stream QUIC carriage (TLS 1.3, epoch ALPN,54 - `internal/adapters/quic`: one-stream QUIC carriage (TLS 1.3, epoch ALPN,
55 exact SHA-256 pin, single bidirectional stream, bounded admission) plus55 exact SHA-256 pin, single bidirectional stream, bounded admission) plus
56 the short-lived SSH bootstrap (ephemeral certificate, 32-byte token,56 the short-lived SSH bootstrap (ephemeral certificate, 32-byte token,
@@ -98,13 +98,13 @@ Interactive observation is a separate opt-in composition. `term.Terminal` remain
98 98
99 A client publishes exactly one of three presentations at a time. `picker` is the local picker: the client is usable and describable without a broker and without a daemon. `connecting` is an attachment attempt that has not committed its first frame. `attached` is a committed attachment, and only it carries the validated session identity, the committed output boundary, and the real actionable generation; `picker` and `connecting` carry the run's stable service handle and their status with every session field zeroed, so a capture can never present session metadata as an attachment and no caller can fence an input action against a generation no attachment committed. The former `detached`, `reconnecting`, and `transitioning` values are removed without alias: a reconnect is `connecting`, a detach returns to `picker`, and terminating closes the UI service instead of becoming a fourth persistent presentation. The presentation is published inside the terminal's UI output transaction by its owner: the supervisor publishes `connecting` before the attachment foreground is granted and `picker` after the run drained and revoked, while the admitted foreground publishes `attached` only after its first frame was written, flushed, and committed.99 A client publishes exactly one of three presentations at a time. `picker` is the local picker: the client is usable and describable without a broker and without a daemon. `connecting` is an attachment attempt that has not committed its first frame. `attached` is a committed attachment, and only it carries the validated session identity, the committed output boundary, and the real actionable generation; `picker` and `connecting` carry the run's stable service handle and their status with every session field zeroed, so a capture can never present session metadata as an attachment and no caller can fence an input action against a generation no attachment committed. The former `detached`, `reconnecting`, and `transitioning` values are removed without alias: a reconnect is `connecting`, a detach returns to `picker`, and terminating closes the UI service instead of becoming a fourth persistent presentation. The presentation is published inside the terminal's UI output transaction by its owner: the supervisor publishes `connecting` before the attachment foreground is granted and `picker` after the run drained and revoked, while the admitted foreground publishes `attached` only after its first frame was written, flushed, and committed.
100 100
101-Session navigation is an autonomous client presentation, not an attachment interaction. While attached, Alt+Space opens the daemon command palette; `SSP` / `session-picker` ends the current attachment with `Detached{Reason: ReasonDetachToPicker}`. The session stays headless. The attachment worker maps this to `AttachmentDetachToPicker` settlement; the supervisor drains and revokes the foreground before giving its input lease and terminal writer to the local picker. Search, sorting, cursor movement, selection, and broker-backed attachment opening are client-owned. No picker bytes or navigation selections are sent to the serving daemon.101+Session navigation is client-owned. While attached, Alt+Space opens the daemon command palette; `SSP` / `session-picker` opens the client picker as an overlay over the live attachment. Cancel returns to the same attachment without reconnecting. Committing a different destination switches attachments through `connecting`; attachment loss or explicit detach leaves the picker as the standalone presentation. Search, sorting, cursor movement, selection, and broker-backed attachment opening are client-owned. Daemon move-destination offers still use the attached worker's separate move picker.
102 102
103-The selected row owns one client-scoped live preview subscription through `ports.BrokerService`. The broker opens sequential observation streams over its existing local or remote physical pool, sends bounded `RemotePreviewRequest` values, and publishes the newest fenced result. Cursor movement and resize replace the subscription with a strictly newer generation; broker loss, commit, picker close, and client exit cancel it. The client accepts a publication only when broker epoch, connection, generation, target, and dimensions still match, so a late capture cannot repaint another selection. Preview cells remain bounded, memory-only, and are never persisted or logged.103+The selected row owns one client-scoped live preview subscription through `ports.BrokerService`. The broker opens one long-lived observation stream over its local or remote physical pool; the daemon pushes changed `RemotePreview` frames at a broker-selected interval (33 ms local, 125 ms remote). Cursor changes are debounced for 80 ms, and the client retains eight recent previews so a selection can remain visible while refreshing. Broker loss, commit, picker close, and client exit cancel the watch. The client checks epoch, connection, generation, target, and dimensions before painting; previews remain bounded, memory-only, and are never persisted.
104 104
105-There is no forwarding or compatibility path through `PickerOffer`. The daemon does not dispatch `client picker request` or `picker control request`, cannot open a navigation interaction, and cannot resolve a `PickerActionNavigate` or `PickerActionKill` interaction selection.105+The daemon does not own the session picker or resolve cross-daemon navigation; it can offer a move-destination picker to the attached client and receives its typed selection or close reply.
106 106
107-Pane/tab move destination pickers are not forwarded through session navigation. The existing daemon interaction remains temporarily available only to the daemon command palette; it captures and revalidates the move source and accepts only move intents. The autonomous attachment worker does not consume that interaction. Explicit scripted move commands remain available. The command palette itself remains daemon-owned and is separate from session-picker presentation.107+Pane/tab move destination pickers are separate from session navigation. The daemon captures and revalidates the move source; the attached worker displays the offer and sends the selected move target back. The command palette remains daemon-owned.
108 108
109 ### Resize repaint fence109 ### Resize repaint fence
110 110
@@ -112,7 +112,7 @@ A terminal resize reaches the client as one coalesced invalidation owned by the
112 112
113 ### Attention and notifications113 ### Attention and notifications
114 114
115-Attention remains a daemon fact. The autonomous picker renders catalogue facts obtained through the broker; it does not subscribe to an attachment's legacy picker interaction. Legacy move-destination interactions retain their own attention refresh machinery.115+Attention remains a daemon fact. The broker publishes it from fresh observations but strips it from durable snapshots. The client's route ledger forwards attention order to the serving daemon for status-bar bells and cross-daemon jump-to-attention; the picker displays session and tab bells. The serving daemon uses that same route snapshot to display remote palette destinations, without monitoring other daemons.
116 116
117 ## Broker-owned hosts and daemon composition117 ## Broker-owned hosts and daemon composition
118 118

Keyboard shortcuts

Single-key shortcuts are on. ctrl k and esc work whatever this says.

ctrl k :
go to a section, branch, tag, file or repository
?
this list
j k
move the row cursor down / up
enter
open the row under the cursor; on Files, a directory opens or closes in place
↑ ↓ ← → home end
in the file tree (focus on a row): previous / next row, close / open a directory or go to its parent / first entry, first / last row. They never open a file
l h
on Files: open a directory or a file / close a directory or go up to its parent, then to the parent page. Elsewhere: into the side panel (on a merge request, its files) / back to the content; there j k move between its controls
g g G
first / last row
/
filter the list; on Files, find a file anywhere in the repository (esc clears, enter opens the best match)
b
switch branch or tag
g s g f g c g b g m g i g r g a
tabs: summary, files, commits, branches & tags, merge requests, issues, releases, actions (when available)
g h
home
w
wide mode: use the whole width of the screen, or not (remembered)
y
copy a permalink pinned to the commit
d u x
diff: split / unified / collapse or expand all
e E
diff: the whole file in view / every file, with the lines the hunks hide
n
merge request: next note in the diff
esc
close a dialog, leave a field

Branches 12

Tags 11

↑↓ moveenter openesc close