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
187
188
189
190
191
192
//! Workspace enumeration across the three roots (DESIGN §3.1). Everything here
//! is a pure function of injected roots plus a bounded directory walk — no env
//! reads (roots come from `crate::xdg`), no writes.
//!
//! §3.1: a workspace is exactly a directory holding `repo.git`. Under yog's own
//! **flat names root** its leaf *is* the chosen name; under litany's roots it is
//! foreign (`workspaces/`, auto-id) or a read-only replay (`replays/`). Three
//! roots, one shape, classification by path alone. The names root is flat by
//! construction — names are direct children — so each root is one readdir.
//!
//! The binding itself is **not** here: a ball is bound to a workspace iff its
//! claimant equals the workspace name (§3.2), joined in
//! [`crate::projects::join`]. The superseded mirrored-path convention
//! (`<yog_data>/balls/<project>/<ball_id>/`) is dead — a location cannot be
//! reassigned but a claim can, and assignment is late-mutable (§3.1/§3.2).
use ;
/// The marker a workspace directory directly contains (§3.1); a workspace is
/// exactly a directory holding this. Matches `git_tree`'s `REPO_DIR`.
const REPO_MARK: &str = "repo.git";
/// A discovered workspace directory and its classification (§3.1). Derived from
/// the tree, never stored.
/// How a workspace is classified, decided by the root it sits under (§3.1).
/// Three roots, one shape, classification by path alone.
/// yog's flat names root (§3.1): `<yog_data>/workspaces/`, the directory whose
/// leaf-named children are yog's own named workspaces. The single home of the
/// `workspaces` path segment, shared by [`workspace_path`] and the app's
/// NamesRoot watch (§7.1).
/// Forward derivation (§3.1/§3.2): the workspace directory a `name` binds to —
/// `<yog_data>/workspaces/<name>/`. The name *is* the path leaf; there is no
/// stored home. A ball bound to this workspace is any ball whose claimant equals
/// `name` (§3.2, joined in [`crate::projects::join`]).
/// Place a leaf under a territory root by the verbatim project mirror
/// (balls arch §11): `<territory>/<project, leading '/' stripped>/<leaf>/`. The
/// convention the bl-delivery worktree root is built on. A relative project
/// mirrors through unchanged (its leading `/` is absent).
/// The bl-delivery work-worktree path for a claim (§3.3, balls arch §11):
/// `<balls_state_root>/plugins/bl-delivery/<project verbatim>/<leaf>/`, where
/// the leaf is `<ball_id>` or, when a claimant disambiguates, `<ball_id>-<claimant>`.
/// Pure — the path is computed, never stored; cross-checked against `bl claim`
/// stdout at claim time.
/// How each of [`roots`]'s three roots classifies its leaves (§3.1), positional
/// with that list — one root, one kind, no third place naming either.
const KINDS: = ;
/// The three workspace roots (§3.1), in classification order: yog's flat names
/// root, then litany's `workspaces/` (foreign) and `replays/`. The single home
/// of that list — [`workspaces`] enumerates it, and
/// [`names::validate`](crate::names::validate) refuses a name equal to any leaf
/// under it, so creation and enumeration can never disagree about where names
/// live.
/// Every workspace across the three roots (§3.1), tagged with its kind: named
/// (yog's flat names root, leaf = name), then foreign and replay (litany's flat
/// `workspaces/` and `replays/`). Each root is one readdir, sorted by path; a
/// missing root contributes nothing — the general path with no inputs, not a
/// bootstrap special case.
/// The name of the workspace at `path`, iff it is one of yog's own
/// (§3.1: the leaf *is* the name). `None` for a foreign, replay, or unknown
/// path — none of which can carry a claimant identity, so none of which can
/// bind a ball (§3.2). The one home of that question: the §3.6 delete gate,
/// the §3.5 join's own binding and the Work tab's attempt lookup all ask it
/// here rather than each re-matching the enum.
/// True when `dir` directly contains the `repo.git` marker — the §3.1
/// definition, callable wherever "is this directory a workspace at all"
/// is the question (the Prepare raise asks it of half-born debris,
/// bl-c9d2).
pub
/// Whether `dir` is a **birth in flight or its debris** (bl-1af5): a workspace
/// is born under an I3 temp name in its own parent and renamed into place when
/// litany has finished, so a directory whose leaf is one of `scratch`'s temps
/// holds a `repo.git` that is not a workspace yet and may never be. Skipping it
/// is I3's own promise kept — *"temp names are dotfiles so no substrate reads
/// them"* — and it is what makes a killed birth inert rather than a wedged
/// name: nothing enumerates it, so nothing refuses the name it was born for.
/// One-level (flat) enumeration: direct children of `dir` that are workspaces,
/// each tagged by `classify` over its leaf name. An absent `dir` contributes
/// nothing. Sorted by path for a stable, determinism-derived roster (I9).
/// `classify` is a bare `fn` (the call sites capture nothing) so the enumerator
/// has one instantiation — no monomorphized-per-closure llvm-cov phantom (§12.1).