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
//! **The followed config commit** (§9.4 as amended by bl-e654) — what control
//! actually resolves from, and the answer every surface that says *which config
//! governs this conversation* renders.
//!
//! litany's operator ruling of 2026-09-01 (upstream bl-403b, its
//! `docs/DESIGN_CONFIG_FOLLOW.md`; landed here at the `=0.0.5` pin) inverted the
//! default this file's sibling was written under. Fork settles only which
//! **lineage** governs; control resolves from that lineage's **current tip at
//! every step boundary**, so a `litany config` edit reaches every running
//! conversation on the lineage at its next step with no per-conversation act.
//! The governing commit ([`super::governing_config`]'s ancestry walk) survives
//! as this derivation's **input**, never again as its answer.
//!
//! The rule, with no special case: take the config heads whose history contains
//! the governing commit and collect their **distinct tips**. Exactly one is
//! [`Governance::Follows`] — the single-lineage case, and equally the
//! freshly-forked case where several refs still stand on one commit. Two or
//! more is real divergence this derivation must not guess between: the fork
//! commit itself resolves, [`Governance::Held`], until `litany retarget`
//! settles the lineage. This is a faithful port of
//! `litany/src/workspace/current_config.rs`, the way the ancestry walk beside
//! it is of `litany/src/workspace.rs::governing_config` — litany keeps its
//! `workspace` module crate-private, so the port is the only way to share the
//! answer, and porting it is what keeps the two sides from disagreeing about a
//! conversation in front of the operator.
//!
//! **yog derives the held state; it does not read litany's notice for it.**
//! litany prints `litany: notice: N diverged config lineages reach [<agent>] …`
//! on the driver's stderr at every step, and that line is its *operator*
//! channel, not a wire. Scraping it back out of `driver.log` is the shape
//! bl-b95e already refused and deleted (`opslog::notice`): a phrase table over
//! sentences litany is free to reword is not a classifier, and content is
//! diagnosis, never a trigger. Held-ness is one fact with one home, and the
//! home is this git query — which both sides run, against the same refs.
use ConfigBranch;
use crate;
use Path;
/// Which lineage governs a conversation, and whether it is being followed.
/// The config commit a conversation's control resolves from (§5.1 #17): the
/// followed lineage's tip, or the fork commit a divergence holds it on. A pure
/// view-model — `oid`/`short_oid`/`files` are all of the **resolved** commit,
/// so a reader never has to know which arm answered to know what governs.
/// Resolve `fork_oid` — the governing commit — against the workspace's config
/// branches: the distinct tips of every lineage whose history contains it.
///
/// A lineage that does not contain the fork commit contributes nothing (it is
/// somebody else's), and tips are deduplicated by oid before they are counted,
/// which is what makes several refs standing on one commit a *followed* case
/// rather than a divergence. Zero cannot occur once the ancestry walk has
/// succeeded — the head that contributed the fork commit contains it — so the
/// count arm is written over `n` rather than special-cased, exactly as
/// upstream's is.
pub