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
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
//! The workspace half of the start flow's executors (DESIGN §8.1, §8.6, §3.7):
//! the idempotent `litany new` ensure and the **policy convergence** that runs
//! **outside** the create skip, so a workspace made a moment ago and one made
//! last week both converge to a config lineage naming the control shim and
//! composing frozen project instructions — **the lineage the drone will fork
//! off** (§8.7), which is `config/default` unless the ball's tags named another.
//!
//! Split from [`super::exec`] at the seam the tests already used: the `bl`-facing
//! executors (create / claim / cross-check) are that file's concern, the
//! workspace's existence and its policy are this one's.
//!
//! **Four files, one drive** (§3.7 item 4, §8.6, bl-0460). §8.6's
//! `tool_control:` block, §3.7's `instructions/**` glob and the worker's
//! `clients` grant **with the description it is worthless without** (bl-7d33)
//! are the control files of one yog policy, and each owns its
//! own fixed point ([`control::author::workflow_drift`], [`manifest::drift`],
//! [`grant::drift`](super::grant::drift)) and knows nothing of the others. This
//! module collects whichever drifted and converges them in a **single** `litany
//! config` pass — one checkout, one commit, one ops row. With none drifted
//! nothing is staged and nothing spawns, which is the steady state of every
//! start after the first.
use ;
use manifest;
use crate;
use crateCli;
use crate;
use cratecontrol;
use crate;
use crateLayout;
use cratestage_root_under;
use io;
use Path;
/// Ensure the bound workspace exists (§8.1, §3.1): skip when `<workspace>/repo.git`
/// is present (resume is the same path as opening). Otherwise `mkdir -p` the
/// parent chain — a failure logs a `["yog-step","mkdir"]` row (Z5) before it
/// returns — and `litany new <workspace>` piped + opslog'd.
///
/// **Birth judges only what exists at birth (bl-00ee).** bl-c3a9 gated the
/// world's birth template here, against brazen's provider table; §16.2's wall
/// made that table the *workspace's*, born empty with the workspace and filled
/// by the operator's per-workspace sign-in afterwards — so the gate read a fact
/// that cannot exist yet and refused every workspace whose template names a row
/// brazen does not ship. The judgement did not move surface: the same
/// `is_unknown_row` faults the provider field in the §9.5 config pane, where
/// the workspace's own wall is a fact, and a row that is still dead at the fire
/// surfaces as the §8.3 auth-shaped step failure with Login one click away.
/// Stage `drafts` and drive the one `litany config <ws> <config>` pass that
/// commits them (§9.3 — the only lawful writer of `config/*`, so yog never
/// writes inside a workspace itself). `None` when nothing drifted: no staging
/// dir, no spawn, no ops row.
///
/// Attributed to the surface that asked for the start (bl-48f8): being born
/// uncontrolled or uninstructed is that start's failure, and it banners where
/// the start was offered.
/// The create half of [`execute_ensure_workspace`]: the parent chain and
/// `litany new`. Skipped whole for a workspace that already exists — resume is
/// the same path as opening.
///
/// **A birth is one act or none** (bl-1af5). `litany new` makes the directory,
/// then the bare repository, then the first `config/default` commit — three
/// steps, and a failure at the third left `<workspace>/repo.git` and nothing
/// else. That debris **is** a workspace by §3.1's definition, so it is
/// enumerated, so a scoped client that never got a registration out of the
/// failed reply can neither address it (`unknown workspace`, REMOTE §4) nor
/// found past it (the raise refuses to join another client's wall), and
/// `workspaces` answers an empty list about a name that is now unusable
/// forever. The state that causes it is invisible to every read the interface
/// offers, and `rm -rf` on the directory is the only exit. bl-c9d2's raise
/// already resumes past a directory with **no** marker; this is the same
/// wedge one step later, where no raise can help.
///
/// So the workspace is born under an **I3 temp name** in its own parent
/// (`.<name>.yog-tmp-<pid>`, §2 I3's one spelling) and renamed into place only
/// once litany has finished — a same-directory rename, so it is atomic and
/// never EXDEV. A failure at any step leaves no workspace: the temp is removed
/// on the way out, and even a process killed mid-birth leaves only a dot-named
/// directory that no enumeration sees ([`crate::binding`] skips I3 temps) and
/// that blocks no name, where the old shape left a name wedged. Three
/// consequences, each deliberate: the §4.2 trail's `new` row names the temp,
/// because that is the path litany was actually given; a debris directory
/// already at the destination is renamed **over** only when it is empty, which
/// is exactly bl-c9d2's case, a non-empty one earning `ENOTEMPTY` where litany
/// used to say `destination is not empty`; and the I3 sweep does not remove a
/// leftover birth, since it removes files and never directories — an inert
/// dot-directory is debris, and the wedge it replaced was a defect.
/// The rename that makes a finished birth a workspace — the one act between
/// litany's last write and the name being addressable.