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
//! The `bl` arm — **filled by W8**: balls' own thin bin, verbatim. The mutating
//! verbs keep their subprocess (balls' change-worktree + ff-only-seal CAS and
//! its plugin chain are process-shaped, §16.7), but the process on the other
//! side is yog. Typed store *reads* never come here — they are in-process
//! ([`crate::projects::runner::BlStore`]).
//!
//! **W9 adds the identity an agent tool needs** ([`crate::world::tools`] seeds
//! the shim that reaches it): [`default_actor`] prefers `$YOG_NAME` over
//! `$USER`, so a verb the caller left unstamped claims under the workspace
//! name — §3.3's `--as` stamp, applied at the one place balls reads the
//! default rather than by rewriting argv. An explicit `--as` still wins, and
//! verbs with no `--as` are untouched. No argv parsing, no per-verb flag table.
//!
//! **The full verb surface runs (bl-2930; the W9 refusal is deleted).** balls
//! binds its sibling plugin binaries (`bl-delivery`, `bl-tracker`) from
//! `Edge::exe_dir` — so the arm converges the world's tool shims and names
//! `world/tools/bl` as the running executable ([`targets`]): `exe_dir` is the
//! tools dir, the seed's sibling rule (`exe_dir/<name>`) finds the plugin
//! shims there, and a `prime` founds a checkout whose plugin chain re-enters
//! yog ([`super::bl_delivery`]/[`super::bl_tracker`]) — the same
//! converge-on-the-way-in the lernie arm does for its re-entry targets (W11).
use Edge;
use env;
use IsTerminal;
use Write as _;
use PathBuf;
use cratetools;
use landing;
/// The workspace-identity env var yog stamps on every workspace-scoped
/// spawn (§8, §3.3); it rides down the whole chain (detached driver → tool
/// subprocess → the agent's bash → this shim), which is what makes it the
/// right default actor.
const YOG_NAME: &str = "YOG_NAME";
/// `yog bl <argv…>` → `balls::run`. Reproduces `bl`'s `main` exactly: the
/// host environment is read ONCE here, at the process boundary, into an
/// [`Edge`] (balls' own rule — the library does no env reads), and the exit
/// code rides back to [`super::dispatch`]. Because the whole env is read
/// live, the nested world a spawn stands on (`XDG_STATE_HOME`, §16.2) lands
/// on exactly the clones/worktrees yog reads. The world's tool shims are
/// converged on the way in (one read, no write, in the steady state) so a
/// `prime` — however reached — binds real sibling paths.
pub
/// Converge the world's tool shims and return the world's `bl` — the path
/// handed to balls as the running executable, so `Edge::exe_dir` is the
/// tools dir where the `bl-delivery`/`bl-tracker` sibling shims live
/// (bl-2930; the W11 lernie-arm mechanism). The tools dir derives from the
/// ambient anchor (`$XDG_DATA_HOME/yog/world/tools`, §16.2 — never a world
/// override, so every process in the chain resolves the same dir).
///
/// **A discovery probe converges nothing** (bl-52ed): `yog bl --help` reads
/// balls' interface, not the world, so it must not materialize six shims under
/// a fresh world root — nor fail outright before help on a read-only one. The
/// exe is still the world's `bl`; for a probe it is only *computed*, and balls
/// answers from argv before it resolves anything the path is used for.
/// The default `--as` identity for an embedded `bl` op (§16.7 W9, §3.3):
/// `$YOG_NAME` when the harness stamped one, else `$USER` (balls' own
/// default), else balls' `"unknown"`. Empty reads as absent, the env
/// convention the rest of yog follows. Pure over the two raw values so every
/// branch is testable without mutating the process env.
pub
/// The host inputs for one embedded `bl` invocation, resolved verbatim as
/// balls' `bl` binary resolves them — except three folds, each at the one
/// place balls reads the value rather than by rewriting argv: the default
/// actor ([`default_actor`]'s `$YOG_NAME`-first fold); the executable, which
/// is the world's `bl` shim ([`targets`]) rather than `current_exe()`, so
/// the sibling-binding seam points at the world tools dir; and **balls' two
/// home directories, which come from the §16.3 space
/// ([`marks::space`](crate::world::marks::space)) rather than from
/// `$XDG_CONFIG_HOME`/`$XDG_STATE_HOME`**.
///
/// That third fold is what makes a per-agent branch possible at all, and it is
/// balls' own seam: balls' library does no env reads (its bl-bfa8 rule), so the
/// host supplies the layout — the same exit §16.2 takes for brazen's
/// credential/cache seams. Absent `YOG_MARKS` it resolves the world's space, so
/// nothing about a project-bound agent, yog's own verbs, or the board's reads
/// changes — except that balls' *config* home stops being the operator's
/// ambient `~/.config/balls` and nests with the rest of the world (§16.3's
/// module doc for what that leak cost).