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
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
//! The conversation's **model row** (§11) and its §9.4 apart clause. "Header"
//! here names the row's shape — what the two dropdowns show, plus the hover and
//! the clause around them — not a seat: the row sits in the bottom settings
//! rows since the settings-seat ruling (§11, bl-2e18).
//!
//! **The row is the selection** (bl-cd2a). The operator's ruling, verbatim:
//! *"Right there, I want essentially that whole line changed to: `<provider> -
//! <model>`. That's it."* So the line carries no `model ·` prefix, no `frozen
//! at <oid>`, and no *change…* button — it carries the pair, in two live
//! dropdowns, and the facts that used to crowd it ride the hover.
//!
//! **What the dropdowns show is what they write, and now also what this
//! conversation runs.** The pair shown is the config lineage tip's. That used
//! to need an argument — a control displaying the frozen pair would report a
//! write it just made as a no-op — and since litany's follow-the-tip ruling it
//! needs none: control resolves the lineage's head at every step boundary
//! (bl-e654, upstream bl-403b), so the tip's pair *is* the conversation's pair,
//! and a pick lands on the conversation in front of the operator at its next
//! step.
//!
//! **The clause survived the inversion by changing sides** (bl-e654). It is
//! still one derived inequality over two oids the caller already holds — the
//! commit this conversation resolves (§5.1 #17, now the followed one) against
//! the workspace lineage's tip, which the §7 snapshot already carries — and
//! still nothing is stored. What differs is what the inequality MEANS. It can
//! no longer mean *frozen behind*, because following is the default; it can
//! only mean this conversation does not resolve this workspace's lineage — it
//! is held on a divergence, or it follows another one. Both are the states
//! `retarget` exists for, which is why the one exit rides here.
//!
//! **Why a clause at all, still.** bl-9786's lesson outlived the doctrine it
//! was filed under: the scope sentence is read at the moment of the *write* and
//! the surprise arrives at the moment of the *read*, so the fact belongs on the
//! row an operator comes back to, not in a caption they saw once.
use ;
/// The workspace's config-lineage tip (§2.2) as a **seat** holds it (REMOTE
/// §9.4, bl-1eb0): the commit `litany prompt` forks the next conversation off.
/// Two strings, because two strings are all the picker asks of it — the row
/// labels with the short oid and reads `providers.yaml` at the full one — and
/// because the `CommitNode` this replaced is a git-derivation record a face
/// holding no repository cannot be handed.
/// One config commit as the row reads it: the oid it is, and the
/// `providers.yaml` its tree carries. Two of these — the governing commit and
/// the workspace default's tip — are the whole input to [`conversation_row`].
/// The model row as painted (§11): what the two dropdowns show, the hover that
/// explains the scope, and — only when this conversation does not resolve this
/// workspace's lineage — the clause naming what it resolves instead.
/// What a dropdown shows when the `providers.yaml` it reads declares no such
/// role: the pair is absent, and absence is a value.
const NO_ROW: &str = "(none)";
/// **The clause's one exit** (bl-2d19, left alone by bl-e654): litany's own
/// `retarget` verb, which re-forks this conversation onto the lineage this
/// workspace runs and replays every commit it has made onto that base — so its
/// whole history survives the move.
///
/// It used to stand beside a second, *new conversation uses the current
/// config*, and bl-9786 ruled them a strip of peers with this one leading
/// because discarding a history is the larger act. The peer is **gone**
/// (bl-e654): it was the escape from a freeze, and there is no freeze to
/// escape — a conversation that merely wants the current config already has
/// it. What is left here is a conversation that resolves a different lineage or
/// none, and starting a new one settles nothing about this one.
pub const RETARGET_EXIT: &str = "settle this conversation onto this workspace's config lineage";
/// What pressing that says (§11 discoverability rule 3, which is also where its
/// keyboard spelling is named): the verb, its timing, and the one thing an
/// operator must know before spending it — that nothing is thrown away.
pub const RETARGET_HOVER: &str = "Mark this conversation to be re-forked onto the config lineage \
this workspace runs (litany retarget) — you do not need this for an edit to \
the lineage it already follows, which reaches it on its own. It keeps every \
message: the re-fork lands at the conversation's next step, with the work it \
has already done replayed on top. Type /retarget to do it without the mouse.";
/// Compose the conversation's model row from the config commit it **resolves**
/// (§5.1 #17's followed answer) and the workspace's config-lineage tip. The
/// dropdowns show `tip`, because that is both what a pick moves and — for every
/// conversation following this lineage — what this conversation runs. `resolved`
/// is named only when the two have parted, which is now the abnormal case.
/// Compose the §11 birth-config block's model row from the config branch's
/// **head** — the commit a fresh root forks off. No apart clause: a
/// conversation that does not exist yet cannot resolve anything else.
///
/// That head is not a yog choice: litany's `litany prompt <repo>
/// <message>` takes no config argument and resolves
/// `ConfigSource::ConfigBranch("config/default")` internally, so "which config
/// is this conversation born on" has exactly one answer and the hover says it.
/// The role a bare row reports and writes — the one that talks to you
/// ([`WORKER_ROLE`]), which the picker's role strip re-scopes while it is open.