1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
//! yog's converging UI state (DESIGN §4.1, §15 Y8) — the four attention `seen`
//! watermarks, `pinned`, `ceiling` and `prices`.
//!
//! **It is one document, and every key in it is a fact about the world**
//! (REMOTE §7 as amended, bl-f936): an acknowledgement, a pin, a spend
//! ceiling — assertions every seat shares, because attention answered on the
//! phone must clear on the desktop (I0).
//!
//! **A fact about a pane of glass is not stored here and never was reachable**
//! — how wide a panel was dragged, what is collapsed, how big the text is.
//! bl-8bbc gave those a second per-client document on the promise that they
//! would converge across one client's seats; the frame that read them left with
//! bl-7942 and no gesture ever replaced it, so for the whole of that document's
//! life nothing wrote a key and no reply carried one. A glass fact is each
//! seat's own local storage (§4.1), which costs a boundary act nothing and
//! keeps this document to the facts that genuinely converge.
//!
//! **Single source of truth:** each document is one [`serde_json::Value`]
//! object (`root`); every known field is a *query* over that map and every
//! unknown key round-trips for free — no parallel typed struct plus extra-map
//! to drift (the "one struct, flattened extra" discipline without a `serde`
//! derive dependency: `serde_json` only).
//!
//! Convergence (§4.1, I5) is last-writer-wins whole-file: forgiving load
//! (missing/corrupt ⇒ default doc, never an error), **write-through** atomic
//! writes (temp dotfile + `rename`, I3), echo suppression by content hash
//! ([`UiState::is_echo`]), and wholesale [`UiState::adopt`] otherwise.
//!
//! **No write is ever in flight.** Every mutator lands on disk before it
//! returns, so the document has no RAM window to lose — not to a SIGTERM
//! (`pkill`, what `make ux` does every iteration), not to a SIGKILL, not to a
//! crash. This dissolves the shutdown-hook problem instead of handling one
//! signal's worth of it (bl-b54e): there is no exit path to flush on, graceful
//! or otherwise. The coalescing a debounce used to buy is bought instead by
//! the same content hash that suppresses echoes — a mutation that does not
//! change the bytes writes nothing at all, so re-acknowledging an already-seen
//! agent is free and a held arrow key writes only on the steps that change
//! something.
/// The §3.5 spend ceiling — `ui.json`'s `ceiling` number (§4.1).
/// The crate's one injected time seam and its one calendar routine — split off
/// at §12's budget and re-exported here, so `ui_state::Clock` and
/// `ui_state::iso8601_extended` stay the one address they always were.
/// One JSON document's file mechanics — forgiving load, echo hash, atomic
/// write-through — spent twice since the REMOTE §7 split (bl-8bbc).
/// The §3.6 workspace prune — a deleted workspace's keys leave the document.
pub use format_iso8601;
pub use ;
pub use SeenKind;
use ;
use ;
use PathBuf;
/// Stable content hash of file bytes — the echo-suppression identity (§4.1).
/// Startup focus (§4.1, §6): first attention-bearing workspace in the caller's
/// derived roster order, else the first, else none. Pure over ids.
/// The live UI-state handle: **one** document (REMOTE §7 as amended, bl-f936),
/// `ui.json`, holding the operator's facts about the world.
///
/// It was two until bl-f936. The second held one client's glass facts and was
/// answered to nobody — no `Action` wrote a key and no `Reply` carried one from
/// the moment the frame that read them left — so the promise it existed for
/// ("a fold answered on the phone clears on the desktop") was never kept by it.
/// A seat keeps its own glass facts; this file keeps what converges.