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
//! **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`, frozen at the config commit its
//! branch forks off. 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 forked after
//! that commit is controlled. Agents already running keep the policy they froze
//! — that is lernie's law, not a gap this could close.
//!
//! **The ruling named a different file, and the tree says it cannot work.** The
//! ruling authored the block into `<LERNIE_HOME>/template/workflow.yaml`, on
//! the premise that `lernie 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 lernie'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 lernie'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 lernie put there. And the
//! write goes through the one lawful writer of `config/*` — the scripted-editor
//! `lernie 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.
use Path;
use crateconfig_file;
use crateDraftFile;
/// The config lineage every workspace is born on and every fresh agent forks
/// off (lernie ARCH §2.2).
pub const DEFAULT_CONFIG: &str = "default";
/// Its refspec in the bare workspace repo.
const DEFAULT_REF: &str = "refs/heads/config/default";
/// The control file inside a config commit.
const WORKFLOW_YAML: &str = "workflow.yaml";
/// The block's key, as lernie's workflow parser reads it.
const KEY: &str = "tool_control:";
/// 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";
/// One committed control file, as `config/default` carries it — the base every
/// authoring starts from. `None` when the workspace has no 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.
/// `base` with any existing top-level `tool_control:` block replaced by one
/// naming `shim`. A **fixed point**: authoring an authored file reproduces it
/// byte for byte, which is the whole convergence test.
/// 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 `lernie config`
/// pass — two files of one policy, one checkout, one commit, one ops row.