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
//! **Wire names** (REMOTE §8, bl-f5f6): how a workspace or a project is
//! addressed when a path may not cross the boundary.
//!
//! A boundary gesture used to carry an absolute `PathBuf`. Across machines that
//! is meaningless — the client's filesystem is not the engine's — and it is a
//! disclosure besides: an operator's home root in every envelope, every deposit
//! file and every reply a seat can read. The wire spelling is the **name**, and
//! the engine resolves it to a path at the one chokepoint that already holds
//! the world ([`dispatch`](crate::boundary::dispatch::dispatch) /
//! [`answer`](crate::boundary::answer::answer)).
//!
//! **Two nouns, and the rule differs because the nouns do.**
//!
//! - A **workspace already has a name**: §3.1 says its directory leaf *is* the
//! name, and §3.2 makes that same leaf the `--as` identity every ball claim
//! is stamped with. So [`leaf`] is the whole rule — no derivation, no second
//! spelling, and **no special case for a foreign workspace**: litany's
//! `workspaces/`/`replays/` leaves are the auto-ids the tab strip already
//! paints as their identity (`nav::tabs::tab`: "the display name is the path
//! leaf"). Two roots holding one leaf is a world whose §3.2 join is already
//! ambiguous — both would claim `--as home` — so [`by_leaf`] refuses it
//! naming the token rather than inventing a disambiguator for a world that is
//! broken one level down.
//! - A **project has no name at all**: its identity is the decoded balls
//! invocation path (§5.1 #1), and two checkouts of one repo legitimately
//! share a basename. So one is derived — [`name_of`], the shortest trailing
//! run of components no other enumerated project shares, which is the
//! basename wherever that is already unique.
//!
//! **It is the same mapping read in both directions.** The frame holds paths
//! and spells the forward reads where a seat's selection becomes a gesture; the
//! engine spells the resolvers where a gesture becomes an act. Nothing is
//! stored: a name is derived from the live enumeration exactly as the §3.5
//! binding and the §11 roster label are.
//!
//! **The roster label is the project name, elided** ([`crate::projects::labels`]).
//! That was `projects`' own private derivation until this module took it, and
//! two copies of "shortest unique tail" would have drifted the moment one
//! learned about a case the other did not — so what the operator reads off the
//! left panel is exactly the word they may type at `--project`.
use ;
/// A workspace's name (§3.1): its directory leaf. Empty for a rootless path,
/// which is never a real workspace — the general path with no input.
///
/// The one definition, read by the §3.2 `--as`/`YOG_NAME` stamp, the §16.2 wall
/// lookup, the search corpus and the boundary's addressing alike.
/// True iff `name` is a **plain path component** — non-empty, no separator of
/// either platform, and not one of the two directory names every filesystem
/// already spends (`.`, `..`).
///
/// The one home of that question (bl-8bbc), because two nouns now become
/// directory names off a wire: a §4 client identity, which is a *certificate's*
/// text and therefore an untrusted peer's, and the §3.1 workspace name a raise
/// founds. A name that could carry a separator is a name that could address the
/// filesystem, and the check belongs beside [`leaf`] — the inverse operation —
/// rather than at each caller.
/// The workspace in `set` whose [`leaf`] is `name`, or the refusal naming the
/// token. Ambiguity refuses too, and says so: a leaf two roots both hold cannot
/// address one workspace, and a guess would act on the wrong world.
/// The wire name of the project at `path` within `set`: the shortest trailing
/// run of `path`'s components that no member of `set` **other than `path`
/// itself** shares, falling back to the whole path when no run is unique.
///
/// **Injective over `set`** — two distinct members cannot name alike, which is
/// what lets [`resolve`] take the first match rather than counting. A `path`
/// the set does not hold names *itself* (no suffix of it occurs, so none is
/// unique), and [`resolve`] then refuses that name — the alias is impossible
/// rather than merely unlikely.
/// The project in `set` that `name` addresses, or the refusal naming the token.
///
/// **A name nothing answers is a refusal, never a guess** — the same strict
/// discipline the gesture codec decodes by (§8.5): a gesture is an instruction,
/// so an address that resolves to nothing must not be silently rewritten into
/// one that resolves to something.
/// How many names an unmatched refusal lists before it stops naming (bl-3377).
/// A refusal is a sentence, not a listing: past this many the operator is
/// reading a directory and the token they typed has scrolled away.
const KNOWN_MAX: usize = 12;
/// **What the caller could have typed**, appended to a refusal that matched
/// nothing (bl-3377).
///
/// `--project` takes the §5.1 #1 derived name — the shortest unique trailing
/// run of path components — and **no gesture answered that set**: `/balls` and
/// `/board` carry a `project` field only for balls that already exist, so on a
/// world with a primed project and no balls (exactly the state after `bl
/// prime`) there was no way to learn the word. The refusal named the token and
/// offered nothing. It carries the set instead of a listing verb existing to
/// carry it, because the refusal is the one place the question is *already*
/// being asked, and because the set is derived here — the one home of both
/// names — rather than assembled by a second reader.
///
/// An empty set says so outright: "nothing here answers to a project name" is a
/// different world from "you typed the wrong one", and the operator must not
/// have to tell them apart by the absence of a list.
/// `path`'s last `k` components, rendered — the whole path when it is shorter.