Sense 63 — The Satellites: connected windows
Sense 63 · Steady · Last touched 2026-08-20
- last_verified: 2026-07-27
Synced from
docs/design/sense_63_the_satellites.mdin the engine repo — that’s the source; this page is a build-time mirror.
Status: agreed; ALL FOUR LEVELS SHIPPED (L1+L2 2026-07-17, L3+L4 2026-07-18). Owner: Miss EDA (sister-7). Named by Mig. Sequel to The Selection (the bus inside one window) and The Diagram (the instruments on it). Doc-first — no code until this is agreed.
The Sense: an JinDesk window is not the workspace — the constellation of windows is. Windows link (never “share”): each declares, per channel, what it sends and what it receives, and chrome-less Satellite windows orbit a master so that plots become free-floating linked instruments — DataDesk’s desk, reborn across screens.
The idea, in one line
Section titled “The idea, in one line”Two browser windows on the same tenant link — not “share” — so that what happens in one (a brush, a navigation) happens in the other, live, with each window choosing what it sends and what it receives.
The founding scenario: window A on page A, window B on page B, both showing the same tenant. Link them on the Selection channel, and from then on one brush scopes both worlds. Unlink, and each keeps its own. And the inverse scenario is just as legitimate: two windows linked on the page but not the selection — navigate in A, B follows to the same page, but each window holds its own cohort. Side-by-side comparison of two selections over an identical view, with one hand steering both.
This is the DataDesk inheritance completing itself: there, every plot was a little window of its own, and all of them answered the same brush. We have the brush (the bus). This gives the bus a reach beyond the window.
Vocabulary
Section titled “Vocabulary”| Term | Meaning |
|---|---|
| Link | The relationship. Windows are linked, never “shared” — a link is directional, per-channel, and revocable. Connection, not copying. |
| Channel | One dimension of linkable state. First two: selection, page. The set grows (candidates below). |
| Send / Receive | Per-window, per-channel declarations. A window may send a channel, receive it, both, or neither. Observer pattern on the receive side, sender pattern on the send side — the two are independent switches. |
| The Hail | The always-on control plane. Every window always listens for control messages (roll call, “everybody listen”, state requests) — even when it receives no content channel. Content is opt-in; being addressable is not. |
| Satellite | A chrome-less auxiliary window (no sidebar, no nav) opened from a master window, pre-linked to it. Working name — see “Naming” below. |
The protocol
Section titled “The protocol”Transport (L1: one browser) — the SatelliteChannel
Section titled “Transport (L1: one browser) — the SatelliteChannel”The wire’s jinflow name is the SatelliteChannel — named for what it is
for, per the DDD ruling “foreign names never surface” (docs/ddd, 2026-07-17):
implementation vocabulary stays behind a jinflow-speaking boundary, exactly as
Bronze wraps SAP’s column names. L1 implements it over the browser’s native
same-origin BroadcastChannel — a name that must not surface (it near-collides
with Sense 55, The Broadcast); L3 re-implements the same SatelliteChannel over
SSE without any vocabulary changing. One channel per tenant:
jinflow:link:<pack>.<tenant>Tenant scoping is structural: messages physically cannot cross tenants, and a window on another tenant never hears them. No server, no polling, no storage.
Envelope
Section titled “Envelope”{ v: 1, // protocol version origin: string, // this window's id (crypto.randomUUID at boot) ts: number, // ordering; last-writer-wins on conflict plane: 'hail' | 'content', channel?: 'selection' | 'page' | …, // content only verb: string, // see below payload?: unknown,}Echo-guard: a window ignores every message whose origin is its own id.
The two planes
Section titled “The two planes”The Hail (control) — always on. Every jinflow window joins the tenant channel at boot and processes control verbs regardless of its link settings:
| Verb | Effect |
|---|---|
hail:who | Roll call. Every window responds with its id, page, link matrix, and whether it’s a satellite. Powers a “linked windows” HUD — you can see the constellation. |
hail:listen <channel> | The “everybody listen” command: asks all windows to switch on receive for a channel. A window may decline (a policy toggle, “ignore hails”), but the default is to obey — this is Mig’s one-gesture “link the room”. |
hail:state? <channel> | Late-joiner handshake: who holds current state? Senders respond with their latest; the joiner adopts the newest ts. |
hail:blink | The attention pulse (see “Attention” in The Diagram): every receiving window blinks the live Selection — asymmetric, ≤ 800 ms, reduced-motion-safe. Fired automatically when a Selection arrives over the Link, or explicitly by a sender; in L3 presenter mode this is the presenter’s laser pointer on every viewer’s screen. |
Content — opt-in per window, per channel, per direction. The link matrix:
send receiveselection [x] [x]page [ ] [x]Each window owns its matrix (a small popover in the header / selection HUD). The matrix is the whole policy — there is no “master” at the protocol level; masters exist only as a default configuration (see Satellites).
Content channels
Section titled “Content channels”selection — payload is the resolved Selection: { anchor, ids }. The
same shape the bus already carries and the same decision as P4a: resolved id
sets travel, not predicates (DataDesk’s shared-case-ids). Receiving window
writes it into its local selection store — every panel updates because they
were already subscribed. Nothing on any page changes.
page — payload is the route identity: { path, params } minus the
selection-bearing search params. Page and selection are separate channels by
construction — that separation is what makes “same page, different cohorts”
possible. Receiving window goto()s the path, keeping its own selection.
Candidates for later (each is a channel, same protocol, zero new
machinery): time range / granularity, scenario, locale, active tab within a
page, scroll-to-entity (“look at this row”), and runs — “what’s
building right now” flowing between windows, reading sister-1’s SIS
run_registry (one row per Run, reds included; shipped 2026-07-17). Channel
shape to be coordinated with sister-1 when a Satellite first wants it — a
run-monitor Satellite on a second screen while the master explores is the
obvious debut. Convergence agreed 2026-07-17 (sister-1’s proposal, note
f5aad2f7): her run_registry + ambient SSE feed supply the data (fleet
variant = a server-side change on her side); runs becomes the third
content channel and the chrome-less run-constellation instrument is the L3
debut piece. On the L3 planning table.
The net has many senders (Mig, 2026-07-17 — correcting a hub that had
crept into the first draft): there is no “cockpit-master” role. ANY window
with send: runs on may broadcast; run summaries are idempotent state keyed
by run_id (last-writer-wins by ts), so overlapping senders converge and
a vanished sender leaves no hole. Direct SSE subscription remains every
window’s sovereign right — the channel is a courtesy relay, never a
dependency; the one-connection economy is emergent, not structural. The
coupling to the runs system stays payload-thin: sister-1’s feed does not
know Satellites exist; Satellites do not know SSE exists.
The Satellite
Section titled “The Satellite”A satellite is a window opened from a master with:
- no sidebar. Period. (Mig, 2026-07-17.) And the topline goes with it —
no persistent identity badges, credentials chrome, bell, or nav bars. A
Satellite is pure glass: the instrument fills the window. Anything
institutional is on demand — the corner chip (the LinkHud, which a
Satellite always carries) doubles as the reveal for identity/session info
when asked. Implementation latitude is explicit here (“or whatever”): the
principle is nothing persistent that isn’t the instrument; the exact
on-demand gesture may evolve. Note what this is NOT: hiding chrome is
display, not authorization — capabilities stay server-enforced; a
Satellite is exactly as signed-in as its browser profile. The flag
(
?frame=satellite) is honoured by the layout; nothing baked into pages; - pre-linked: receives
page+selection, sendsselection(you can brush in a satellite and the master follows) — defaults, editable like any window’s matrix; - opened by three affordances:
-
“Open as window” on any panel — the panel detaches into a satellite showing just itself. This is DataDesk literally: every plot its own little window, all answering the same brush. A second screen becomes a wall of linked instruments.
-
“New linked window” on a page — the whole page, chrome-less.
-
The Launch (Mig, 2026-07-17): a dedicated CLI verb —
Terminal window jin satellite <pack.tenant> [page] [--recv selection,page] [--send selection]opens the default browser as a Satellite (chrome-less, pre-linked with the given matrix; defaults as above). The terminal is a jinflow home: launching instruments belongs in the verb namespace like
jin exploredoes. A scriptedjin satellite× N is how a wall of instruments boots in one command.
-
A Satellite can be a sender. (Mig, 2026-07-17 — and the modal verb is
the principle.) Capability, not state: a Satellite is a full protocol peer,
able to send any channel — but whether it actually sends is decided by its
matrix, like every other window. Wired as its owner chooses, a Satellite
brushes and the master (and every other receiver) follows; it can even send
page and steer the constellation’s navigation. Equally legitimately, its
send switches stay off and it is a pure observer. “Master” describes the
opening gesture and the pre-filled matrix, never a privilege. What no
implementation may do is remove the capability — a receive-only Satellite
by policy is fine; a receive-only Satellite by construction is forbidden.
The master/satellite distinction is only the opening gesture + defaults. A satellite is a full citizen; close the master and the satellite survives, merely unlinked.
Joining is self-service. (Mig, 2026-07-17.) A normal window — full
chrome, opened by hand, linked to nothing — can promote itself into the
current Constellation at any time: open the link matrix, switch on what it
wants to send and receive, done. No invitation, no master’s consent, no
difference on the wire between a born-linked Satellite and a self-promoted
window. The Constellation is defined by who is linked, not by how anyone
arrived. (The Hail makes self-promotion discoverable: hail:who shows a
joining window what already exists; hail:state? hands it the current
selection on arrival.)
Naming (settled 2026-07-17)
Section titled “Naming (settled 2026-07-17)”Mig named the Sense The Satellites — the individual chrome-less window is
a Satellite, and the ensemble of linked windows is the Constellation
(the hail:who roll call literally draws it). The relationship keeps its own
verb: windows link — linking, not sharing. Rejected candidates for the
record: the Wing (architectural, fits Studio/Salon but says nothing about
motion-following), the Mirror (wrong — implies full replication, but a
Satellite may hold its own selection), the Loupe (taken by Diff Loupe).
Phasing
Section titled “Phasing”| Phase | Scope | Transport |
|---|---|---|
| L1 | selection channel + link matrix UI (LinkHud) + hail (who / listen / state / blink) — SHIPPED 2026-07-17 (fb31dd24) | BroadcastChannel |
| L2 | page channel + Satellite windows (detach-panel, chrome-less flag, jin satellite) — SHIPPED 2026-07-17 (8ef9729a+73892832+98652c4f) | SatelliteChannel |
| L3 | Same envelope over the server leg — SHIPPED 2026-07-18, spec below | SatelliteChannel (SSE leg) |
| L4 | The Desk — named constellations in the SIS — SHIPPED 2026-07-18 | SIS |
L3 — the SatelliteChannel’s server leg
Section titled “L3 — the SatelliteChannel’s server leg”Approved by Mig 2026-07-18, including the identity rule.
The same envelope, a second transport: a per-tenant hub inside JinDesk server. Windows opt in (“server link”); the browser leg (BroadcastChannel) keeps serving same-browser windows, the server leg reaches other browsers and other machines — and both carry identical envelopes, so no vocabulary or protocol changes. This is what makes presenter mode real: you brush, every linked viewer’s JinDesk follows and blinks.
Wire: GET /[tenant]/api/link/stream (SSE, one connection per window) ·
POST /[tenant]/api/link/publish (one envelope per call, fanned out to every
subscriber of that tenant). The hub is in-memory per server process — exactly
the lifetime a live gesture deserves; nothing is stored.
Envelope additions: id (per-envelope UUID — a window bridging both legs
would otherwise deliver duplicates; receivers keep a small seen-set) and
identity (the sender’s principal, stamped server-side on publish — never
client-claimed). The browser leg carries no identity; same browser = same
person by construction.
The identity rule (Mig’s ruling): hail:listen obeys automatically when
the sender’s identity is your own — your phone is still your desk. A FOREIGN
identity’s hail:listen requires an explicit accept in each window (”
Authorization: subscribing and publishing require the tenant’s ordinary view capability — the Link shares pointers (ids, paths), never data; each window’s own session resolves what it may actually see. A viewer who cannot see the tenant sees nothing, linked or not.
L4.1 — the Desk restores the wiring, not the furniture (PROPOSED)
Section titled “L4.1 — the Desk restores the wiring, not the furniture (PROPOSED)”⚠️ PROPOSED — NOT BUILT. Everything in L4.1/L4.2 below describes work that has been decided, not shipped. The Satellites themselves (L1–L4) are live; screen-aware Desks are not. (s7’s call, 2026-08-03: don’t advertise unbuilt furniture, don’t hide the shipped feature.)
Proposed by sister-3, 2026-08-02, out of Mig reading L4 back while we looked at pinning Desks to the personal room. Sense 63 is Miss EDA’s — this is a proposal into her doc, not a settled change. Nothing here is built.
The scenario that exposed it. A user opens four ordinary windows, tiles them a quarter-screen each, links them, saves a Desk. Reopening does not give the four tiled windows back. Mig’s read; the code agrees.
Capture is sound. saveDeskNow fires hailWho(), waits 350 ms so late
windows answer the roll call, and stores self + every hailed peer. All four
windows are recorded.
Reopen falls short in two independent ways.
- Geometry was never in the model. A
DeskWindowis{path, satellite, send, recv}— no x, y, width or height in the type or inwindows_json. The tiling is not lost on reopen; it is never captured. - Ordinary windows come back as tabs.
openDeskcallswindow.open(u, '_blank', w.satellite ? 'popup=yes,width=880,height=620,…' : ''). An empty feature string yields a tab. Onlysatellite: trueentries get a real window, and those at a fixed 880×620 cascaded 60 px apart — nobody’s layout.
So the four-window Desk reopens as: this window navigates to the first entry, and three tabs appear.
What L4 does restore, and restores well: which page each window held, its
satellite flag, and the whole link matrix — send/recv are re-encoded as URL
params, so the Constellation comes back correctly wired. The Desk is a wiring
diagram, not a furniture plan. That is a defensible thing for it to be; it is
just not what “your desk, as you left it” promises.
Proposal A — capture the furniture
Section titled “Proposal A — capture the furniture”DeskWindow gains optional geometry (screenX, screenY, outerWidth,
outerHeight), and reopen passes explicit width/height/left/top for every
entry, not only satellites. Optional because a Desk saved before this exists has
none, and a window may not be able to read its own.
Three honesty points that belong in the decision, not in the implementation:
- A window can read its own geometry; it cannot read a peer’s. Peer
geometry would have to travel in the
hail:whoroll-call payload, which makes this a change to the L1 Hail envelope — s7’s call, not a Desk-local patch. - Positioning a tab is impossible. Restoring furniture means every non-first entry opens as a popup window. A Desk saved from four ordinary windows would reopen as one window plus three popups — a real behaviour change, and the closest thing to what the user drew. It should be decided, not slipped in.
- The OS gets a vote. Browsers clamp or ignore position on some platforms,
and a multi-monitor
screenXcan land off-screen on a laptop-only session. Reopen must clamp to the available screen rather than trusting stored numbers.
Proposal B — the popup-gesture problem
Section titled “Proposal B — the popup-gesture problem”Several window.open calls from one click is classic blocker territory: the
first is typically allowed, the rest blocked. Even today’s satellite path is
fragile this way. Options: (i) require “allow popups for this host” and say so;
(ii) reopen one window per click (“Open next window (2 of 4)”); (iii) degrade
to tabs when popups are denied.
Recommendation: (i) with (iii) as fallback, and an explicit message either
way. What must never happen is a half-restored Desk that looks like the whole
one — the same failure the personal room’s protocol was just rewritten to
eliminate (the_personal_room.md, “Saying what happened”).
Proposal C — a Desk has no URL
Section titled “Proposal C — a Desk has no URL”Surfaced by the personal room: a pin is fundamentally an href, and a Desk is
reconstituted by client-side JS (openDesk) with no route behind it. The pin
spec assumed /{tenant}/desk/{desk_id}; no such route exists.
- Give Desks a route.
/{tenant}/desk/{desk_id}loads the Desk and runs the reopen behind a click (Proposal B). Desks become addressable — pinnable, bookmarkable, and answerable to “send me your desk”. - Let a pin carry an action.
kind='desk'renders a button that callsopenDeskdirectly. Cheaper, but pins stop being uniformly links and the Desk stays unaddressable.
Recommendation: 1. Addressability is worth more than the work it saves, and it is the only option that makes a Desk shareable.
Decided (Mig, 2026-08-03)
Section titled “Decided (Mig, 2026-08-03)”- The room, not the wiring. A Desk restores the furniture. Proposals A and B
are accepted, with the costs they carry (peer geometry enters the
hail:whopayload; non-first entries become popups). - Desks get a route (Proposal C).
- And further: the Desk is screen-aware — see L4.2, which supersedes the geometry half of Proposal A.
L4.2 — the screen-aware Desk (PROPOSED — NOT BUILT)
Section titled “L4.2 — the screen-aware Desk (PROPOSED — NOT BUILT)”Mig, 2026-08-03: “I’d love to see the room. And I’d like to go even further — screen awareness. We should store the screen resolution. My layouts on my laptop are different than on my 32-inch.” Specced by sister-3; the Hail half is s7’s.
The requirement is sharper than scaling. Not “one layout stretched to fit” — genuinely different arrangements per screen. Four windows quartered on the 32-inch may be two windows stacked on the laptop. A layout is only meaningful relative to the screen it was authored on.
The model — a Desk holds layouts
Section titled “The model — a Desk holds layouts”desk: desk_id: morning-wall name: Morning Fleet Wall layouts: - screen: { w: 2560, h: 1440, avail_w: 2560, avail_h: 1415, dpr: 2 } windows: - { path: /r.delta/fleet, satellite: false, send: {...}, recv: {...}, x: 0, y: 0, w: 1280, h: 1415 } - screen: { w: 1512, h: 982, avail_w: 1512, avail_h: 944, dpr: 2 } windows: [ … a different, smaller constellation … ]A layout is a complete constellation, not a geometry patch over a shared
window list — because the window set legitimately differs per screen. The
screen block is the signature; w×h identifies it, the rest informs remapping
and diagnostics.
Save — additive, never clobbering
Section titled “Save — additive, never clobbering”Saving on a given screen creates or replaces only that screen’s layout; every other layout survives untouched. This is the behaviour that makes the feature feel right: arranging your laptop desk must not destroy the one you built on the 32-inch.
Reopen — match, else remap, and say which
Section titled “Reopen — match, else remap, and say which”- Exact signature match → restore verbatim. The common case, and the point.
- No match → take the nearest layout (closest aspect ratio, then area) and
remap proportionally into the current
avail_w/avail_h, clamping every window to the visible area. - Either way, say so. A remapped desk announces itself (“laid out for 2560×1440, adapted to this screen”) — never silently misplaced windows. Same rule as everywhere else: an approximation that looks like the real thing is the failure mode worth engineering against.
Updating an open Desk
Section titled “Updating an open Desk”Mig, 2026-08-03: “Can a desk be updated? Open a desk, adjust a window position, update?”
The store already can; the UI cannot. saveDesk is an upsert
(ON CONFLICT (tenant_id, desk_id) DO UPDATE) and the endpoint accepts an
explicit desk_id — but saveDeskNow never sends one. It prompts for a name
and derives the id by slugifying it, so today “update” means retyping the name
exactly, and both outcomes are silent: type it identically → you overwrite with
no confirmation; type it differently → you get a second Desk instead. The user
cannot tell which happened.
The missing piece is that nothing knows a Desk is open. openDesk navigates
and spawns windows but records no identity, so there is no “this Desk” to update.
The route supplies it. /{tenant}/desk/{desk_id} is the Desk’s identity,
and every window it opens carries ?desk=<id>. From that follows:
- Update — an explicit action, sending the known
desk_id, offered only when a Desk is open. Labelled with the target (“Update Morning Fleet Wall”). - Save as new — the current prompt-for-a-name path, and the only way to create.
- Never a silent collision. Saving a new Desk whose name slugifies onto an existing id must say so and offer update-or-rename, rather than quietly replacing someone’s constellation.
With L4.2 this becomes the primary gesture rather than a convenience: open a Desk on the laptop, nudge a window, Update — and per the additive-save rule that replaces only this screen’s layout, leaving the 32-inch arrangement untouched.
The route and the popup problem solve each other
Section titled “The route and the popup problem solve each other”Proposal C’s /{tenant}/desk/{desk_id} is not just addressability. Restoring
furniture requires popups, and several window.open calls need a user
gesture or the browser blocks all but the first. So the route renders a small
pre-flight: which layout matched, how many windows will open, whether this
screen is an exact match or a remap — and one button that performs the reopen
inside the click. The gesture problem disappears into a UI that was worth
having anyway.
The envelope’s rules (s7, 2026-08-03 — load-bearing)
Section titled “The envelope’s rules (s7, 2026-08-03 — load-bearing)”Capture crosses into L1’s protocol, so the constraints are hers:
- Self-reported, never peer-read. Each window reports its OWN
{x,y,w,h}- screen signature into
hail:who; no window reads another’s. The coordinator assembles the roll call from self-reports, which keeps the envelope’s self-owned-state discipline intact.
- screen signature into
- “Ids travel, data never” is not broken. That invariant guards tenant data. Window geometry and screen are UI metadata about the window itself, so they ride the wire with no auth gate. Stated explicitly so nobody reads the invariant as weakened.
- Same-identity only. Geometry and screen travel only among one identity’s own windows — a Desk is inherently “my windows across my screens”. They are NEVER emitted to a foreign identity: a presenter-mode viewer receives my selection, never my furniture. It is private, and useless to them besides — they cannot reposition my windows. The Constellation’s consent model stays whole: foreign identities get pointers, not my desktop.
Window geometry stays out of the selection bus. The selection envelope is
{anchor, ids} — lean and high-frequency. Furniture rides the capture-time roll
call, a different cadence entirely. Two envelopes, two purposes.
“Geometry” here means the furniture, not the brush. Two different things wear that word, and the collision has already confused a reader (Mig, 2026-08-03). Window geometry = a window’s
{x,y,w,h}+ screen — the subject of this section. A brushed rectangle or lasso is something else entirely: a spatial predicate, first-class inside a Selection ({entity, predicates[], combine}→Set<id>, see The Selection). Nothing here restricts it.What the bus carries today is the resolution, not the shape: brush a box, the ids it resolves to travel, the box does not (
SelectionState = {anchor, ids}). Whether a spatial predicate should ALSO travel — so a peer on a different layer can re-resolve it, so a 500k-id selection stays one bbox on the wire, so a peer can draw where you brushed — is a live question for the Selection bus’s owners, not something L4.2 settles.
Boundaries, honestly
Section titled “Boundaries, honestly”- A window can read its own geometry, never a peer’s — hence precision 1 above: capture is self-report into the roll call, not inspection.
- Multi-monitor is a v2.
window.screendescribes the current monitor;screenX/screenYcan place a window on another, but the browser won’t enumerate the arrangement without the permission-gated Window Management API (getScreenDetails()). V1 captures the current screen and clamps; a true multi-screen Desk is an opt-in follow-up, not a silent half-feature. - The OS gets a vote. Platforms clamp or ignore requested positions. Reopen proposes; it never assumes it won.
- Signatures are not stable forever. Changing OS display scaling changes
w×hand orphans a layout into the remap path. Acceptable: it degrades to “adapted”, not to broken.
Build order
Section titled “Build order”- Capture (own window) — geometry + screen signature on save. No protocol change; a single-window Desk already round-trips.
- Capture (peers) — the
hail:whopayload carries geometry + screen. s7’s envelope; blocks multi-window fidelity. - The route —
/{tenant}/desk/{desk_id}+ pre-flight + gesture-scoped reopen, and the?desk=identity that makes Update possible. BUILT 2026-08-05 against today’s wiring-only restore, as sequenced. The pre-flight states plainly that it restores the WIRING, not the furniture, so the page cannot over-promise what capture has not yet delivered; blocked popups are counted and reported rather than leaving a half-restored desk looking whole.kind='desk'inthe_personal_room.mdis unblocked and shipped with it. - Match / remap — exact-signature restore, nearest-layout remap, the announcement.
- Multi-monitor — Window Management API, opt-in.
Boundaries and honesty
Section titled “Boundaries and honesty”- Same tenant only. The channel name enforces it; there is no cross-tenant linking, consistent with tenant isolation.
- Ids travel, data never. A selection message carries entity ids, not rows. Same-origin windows could read each other’s data anyway, but L3 (server transport) inherits this cleanly: the wire carries pointers, each window’s own authorized session resolves them.
- No hidden coupling. A window that neither sends nor receives behaves exactly as today. The bus inside a window is untouched; the Link is a transport behind the existing selection store, invisible to every panel.
- Conflict model is trivial by design: last writer wins, per channel. Two
simultaneous brushes in two sending windows resolve by
ts— acceptable for a human-speed gesture; no CRDTs until reality proves we need them.
Open questions for discussion
Section titled “Open questions for discussion”Naming— settled: Sense 63 The Satellites; window = Satellite, ensemble = Constellation, relationship = link.hail:listendefault-obey: right for a trusted single-user desktop; should L3 (multi-person) require explicit accept per window?- Should the link matrix persist across reloads (localStorage per window is shaky — windows have no stable identity across sessions) or is L4’s named link-group the only persistence?
- Does
pagefollow include search params like sort/filter state (full view replication) or the bare route? Proposal: bare route + a separateview-statechannel later, same reasoning as page ⊥ selection.
Numerical neighbors: ← Sense 61: The Strata · Sense 64 — The Docent: the tour as a declaration →