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
//! **Authoring the control into a workspace** (DESIGN §8.6, VISION §4.11 item 2):
//! the one write this module makes, and the reason every drone is born
//! adjudicated.
//!
//! An agent's policy is its `workflow.yaml`, resolved from the config lineage
//! its branch forked off — at that lineage's **head, at every step boundary**
//! (litany's follow-the-tip ruling, upstream bl-403b; yog bl-e654). So the
//! control is authored **onto `config/default`, at every start**: a workspace
//! created a moment ago and a workspace created last week both converge to a
//! tip that names the shim, and every agent on that lineage is controlled —
//! including the ones already running, from their next step. That last clause
//! is new. It used to read *agents already running keep the policy they froze*,
//! and the convergence-at-every-start shape was the only reach this write had;
//! the shape survives the ruling unchanged and now reaches further than it was
//! designed to, which is the outcome to want from an inversion, not a reason to
//! revisit it.
//!
//! **The ruling named a different file, and the tree says it cannot work.** The
//! ruling authored the block into `<LITANY_HOME>/template/workflow.yaml`, on
//! the premise that `litany prime` seeds that file and later seeding is
//! seed-if-absent. Verified against the pin, all three halves are false:
//!
//! - `prime` never touches `template/` — it is an *override* root, absent by
//! default ("policy lives in config, not code", at litany's own constant).
//! - The override is a whole-file `fs::copy`, not a merge. A `workflow.yaml`
//! carrying only `tool_control:` would delete `events:` — and with it every
//! dispatch — from every workspace born after it.
//! - Authoring a *complete* override would need litany's embedded default, and
//! the crate's `template` module is private. There is no lawful read of it.
//!
//! So the base is taken from where it is undeniably correct: the workspace's own
//! committed `workflow.yaml`, which is exactly what litany put there. And the
//! write goes through the one lawful writer of `config/*` — the scripted-editor
//! `litany config` drive (§9.3) — so yog still never writes inside a workspace.
//! This is *stronger* than the template route rather than a retreat from it: the
//! template only reached workspaces born after it, while this reaches every
//! workspace on its next start.
//!
//! Idempotence is by comparison, not by memory: [`authored`] is a fixed point,
//! so a tip that already carries the block computes to itself and nothing is
//! staged, nothing is spawned, and no commit is authored.
//!
//! **The same fixed point holds one other thing, and holds it empty: there is
//! no conversation budget** (bl-56af). litany's `workflow.yaml` may carry a
//! `budgets:` block — `max_total_tokens`, `max_wall_seconds`, `max_depth`
//! (litany ARCH §6) — and every axis of it is a **whole-tree** consumable, one
//! allowance a root and its whole descent spend together. lernie's pre-`0.0.11`
//! template shipped it *set*, so every workspace born before that release froze
//! `max_wall_seconds: 3600` and `max_depth: 4` into its `config/default` and
//! caps every agent forked off that lineage. A template only ever reaches
//! workspaces born after it — this convergence
//! is the only thing that reaches the ones already standing, which is the same
//! argument that put the control here.
//!
//! **The shipped template carries a `budgets:` block again, and this strip is
//! unchanged** (litany 0.0.12, upstream bl-c701, checked at yog bl-9ced).
//! `template/workflow.yaml` now ships `budgets:\n max_depth: 5` — depth only,
//! neither spend ceiling — and litany's own comment beside it names yog as the
//! consumer that severs it. So the seed is back, on a different axis, and the
//! pass below removes it exactly as it removed the pre-`0.0.11` one: the strip
//! is on the **block**, by top-level key, never on an axis, so an upstream
//! template that adds, drops or renames a limit needs no edit here.
//! `max_depth` is a real prohibition on growth for the plain-`litany` operator
//! (bl-d023's runaway crossed depth 4 before a person ended it) and yog's
//! answer to that concern is not a per-tree number: it is the ui.json
//! `ceiling` below plus the operator standing at the board, and two ceilings
//! over one concern is the second representation that drifts.
//!
//! So [`authored`] **strips** a top-level `budgets:` block and leaves one line
//! saying so. Unconditionally, not down to a smaller number: a whole-tree
//! ceiling ends a conversation that is still working, which is the expensive
//! failure DESIGN §3.5 already reasons about — and yog's own ceiling, the
//! `ui.json` `ceiling` key, is that reasoning's answer (dollars, absent by
//! default, gating a *birth* and never a live drone, spoken on the V4 board
//! ahead of the spawn it will bind). Two ceilings over one concern is the
//! second representation that drifts; the one yog authors is the one it can
//! remove.
use Path;
use crateconfig_file;
use crateDraftFile;
/// The config lineage every workspace is born on and every fresh agent forks
/// off (litany ARCH §2.2).
pub const DEFAULT_CONFIG: &str = "default";
/// The refspec of `config/<name>` in the bare workspace repo.
/// The control file inside a config commit.
const WORKFLOW_YAML: &str = "workflow.yaml";
/// The block's key, as litany's workflow parser reads it.
const KEY: &str = "tool_control:";
/// litany's whole-tree spend ceiling (litany ARCH §6). The second top-level
/// block this fixed point holds, and the only one it holds **empty** — yog
/// authors no ceiling and removes whichever one the template of the day
/// seeded (`max_wall_seconds`/`max_depth` before `0.0.11`, `max_depth: 5`
/// again since `0.0.12`).
const BUDGETS: &str = "budgets:";
/// The prefix of the one comment line yog authors. Stripped by the same pass
/// that strips the block, so authoring stays a fixed point: a note that
/// survived its own block would accrete one copy per start.
const MARK: &str = "# yog authors this block";
/// The prefix of the note left where the ceiling was — same discipline as
/// [`MARK`]: stripped by the pass that re-authors it.
const BUDGETS_MARK: &str = "# yog holds this file's budgets";
/// One committed control file, as `config/<config>` carries it — the base every
/// authoring starts from. `None` when the workspace has no such config commit
/// yet or the file cannot be read: nothing to author onto, which is not an
/// error, only nothing to do. Shared with §3.7's `manifest.yaml` author: two
/// files, one read of the same lineage tip.
///
/// **The lineage is a parameter because the drone's is** (§8.7, bl-380f). It is
/// [`DEFAULT_CONFIG`] for every untagged start, and the ball's tag-selected
/// lineage otherwise — the control must land on the branch the agent will
/// actually fork off, or a tagged birth is the one birth nothing adjudicates.
/// `base` with any existing top-level `tool_control:` block replaced by one
/// naming `shim`, and any top-level `budgets:` block removed. A **fixed
/// point**: authoring an authored file reproduces it byte for byte, which is
/// the whole convergence test.
///
/// Two blocks, one pass, because they are one file's fixed point — a second
/// transform over `workflow.yaml` would be a second answer to "what does this
/// file say when yog is done with it".
/// The note left where the ceiling was, so the absence of one is **stated**
/// and not merely true — a cap that binds a conversation must never again be
/// a number only the file knows.
/// The block yog authors, with the note that says whose artifact it is.
/// `workspace`'s `workflow.yaml` drift against a tip naming `shim`, or `None`
/// when the tip already carries the block — the steady state, which reads one
/// file from git and stages nothing.
///
/// The drafted file is the **whole** `workflow.yaml`: the scripted editor
/// copies files over the checkout, so a fragment would truncate the policy.
/// Who *drives* the commit is [`crate::start::execute_ensure_workspace`], which
/// converges this drift and §3.7's `manifest.yaml` drift in one `litany config`
/// pass — two files of one policy, one checkout, one commit, one ops row.