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
//! The repository's own merge path: what it is handed, and what it leaves behind.
//!
//! The merge path is the verifier. For a remote-first identity that is the host's
//! required checks on the change request; for a local-first one it is the
//! repository's `pre-push` hook, which git runs at the publishing push. This crate
//! runs neither — it hands the merge path the one thing it cannot work out for
//! itself, and it keeps what the path wrote.
//!
//! **The comparison identity** is the remote and base this change is being
//! published onto, exported as environment. A judging process left to discover its
//! own base resolves the repository default, which for a stacked change is not the
//! base the push is publishing onto — so a memoizing tier records its verdict under
//! a key the publishing push never looks up, and re-judges findings the worker
//! never saw and can no longer clear.
//!
//! **The preserved log** is what a publishing push wrote, kept where it outlives
//! the tree the publication was built in.
use ;
use crate;
use crate::;
/// The remote every process judging this change resolves.
pub const COMPARISON_REMOTE_ENV: &str = "ONEVCS_COMPARISON_REMOTE";
/// The base every process judging this change resolves.
pub const COMPARISON_BASE_ENV: &str = "ONEVCS_COMPARISON_BASE";
/// The per-branch directory that outlives the tree a publication was built in.
///
/// Spelled as it always has been, deliberately. This is an **on-disk layout**
/// rather than a name in the source: `sweep` decides whether a run root may be
/// reclaimed by whether a verdict was ever recorded under it, and every run root
/// an earlier build left behind carries this directory. Renaming it would leave
/// each of those answering that nothing judged it, which is the answer that keeps a
/// workspace forever.
pub const PRESERVED_LOG_DIRNAME: &str = "gate-logs";
/// How many invocations one branch keeps, so a branch re-pushing through a red
/// merge path cannot grow the directory without end.
pub const PRESERVED_LOG_ATTEMPTS: usize = 10;
/// The one comparison identity, as environment every judging process reads.
///
/// One source, because two copies of this contract are how the two sides drift.
/// Preserve one merge-path invocation's evidence where it outlives the tree it ran
/// in.
///
/// A run worktree is removed as soon as its session settles, so a *passing* merge
/// path used to leave nothing readable once the work landed while the *failure* it
/// superseded stayed on disk. One file per invocation, numbered in the order they
/// were claimed: reading the second of four attempts out of one appended log meant
/// counting bytes into it. A number another writer already claimed is never written
/// over, so a retry beside the recovery of what it replaced cannot share a file.
/// Whether the merge path has recorded any verdict at all under one run root.
///
/// The proof that a landing got as far as being judged, which is half of what makes
/// its run root reclaimable. A preserved log is written for a verdict either way —
/// the push the merge path accepted and the one it refused — so its absence means
/// nothing this crate ran ever reached one there, and a run root that cannot show it
/// was judged is retained rather than reaped.
///
/// What counts is a **regular file whose name is one [`preserve_log`] writes**, and
/// nothing about its contents: a push whose output was empty said as much as one
/// that printed a page. Both halves are the boundary. This directory is under a
/// state root a host shares, so the name is read through the same
/// [`attempt_number`] that names an attempt rather than by prefix and suffix — a
/// `gate-notes.log` somebody dropped beside the evidence, or a `gate-1.log` spelled
/// the way this crate never writes one, is not a verdict this crate reached. And a
/// *directory* wearing an otherwise perfect name would answer for a verdict nobody
/// reached, so the entry has to be a file.
/// The attempt one preserved log's filename names, or nothing if it names none.
///
/// One reader for the one name [`preserve_log`] writes, so what counts as a
/// recorded verdict, what counts when the next attempt is numbered, and what
/// retention may spend cannot come to disagree about the same file.
///
/// The spelling is **exactly** the one that function writes: `gate-`, four digits,
/// `.log`, numbered from `0001`. This directory sits under a state root a host
/// shares, so a looser reader is the difference between reading this crate's own
/// evidence and reading whatever else is in there — a `gate-1.log` is not a name
/// this crate has ever written, and treating it as an attempt would let it answer
/// for a verdict nobody reached and put somebody else's file under a bound that is
/// not its.
/// The highest attempt number this branch's directory has ever recorded.
/// Keep the newest [`PRESERVED_LOG_ATTEMPTS`] attempts, and spend nothing else.
///
/// What it may remove is what [`preserve_log`] wrote — read through
/// [`attempt_number`], and a regular file — for the reason [`has_recorded_verdict`]
/// reads names the same way: retention *deletes*, so anything in this shared
/// directory that this crate did not write is somebody else's file rather than the
/// oldest of ours. Sorting by name is sorting by attempt, because the number is
/// zero-padded to a fixed width.