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
//! **The workflow mark, read** (§9.4 as amended by bl-b680; litany ARCH §6
//! *The workflow mark*, upstream bl-5c02) — the one control fact with a
//! per-agent override, and the second per-agent fact this tree ports rather
//! than scrapes.
//!
//! litany's `workflow.yaml` follows the governing lineage's tip like every
//! other control fact ([`super::follow`]), and `litany workflow <ws> <agent>
//! --config <lineage>` writes the **standing** ref
//! `refs/litany/workflow/<agent>` at that lineage's head: from the agent's
//! next step boundary on, *that* commit's `workflow.yaml` governs instead of
//! the followed tip's, until re-marked or cleared. Resolution is **nearest
//! mark on the agent's descent** — the agent's own id, then each ancestor by
//! the §2.3 token arithmetic — so marking a root switches its whole tree and
//! a child's own mark overrides its ancestors'. This file is a faithful port
//! of litany's `prompt/resolve/workflow_source.rs::nearest_mark` and
//! `cmd/workflow.rs::lineage_at`, on [`super::follow`]'s precedent exactly:
//! litany keeps its `workspace` module crate-private, the verb's read mode
//! answers one prose line on stdout, and bl-b95e ruled a sentence litany is
//! free to reword a diagnosis and never a trigger — so both sides run the
//! same git query against the same refs, which is the one place the fact
//! lives.
//!
//! **What it says, and what it does not.** A mark moves `workflow.yaml`
//! alone: `providers.yaml`, the souls and the manifest keep following the
//! tip. So the answer rides *beside* [`super::GoverningConfig`] on the wire
//! rather than replacing its `oid` — the commit-side facts still describe
//! the followed tip, and this names the one file that comes from elsewhere.
//! The **lineage** is recovered from the marked commit rather than stored
//! with it, because the mark names a commit and not a name: a lineage that
//! advances after the mark changes nothing the agent reads, and a mark left
//! standing on an older commit is rendered as the absence it is (`None`)
//! rather than declined.
use config_branches;
use crate;
use Path;
/// litany's mark namespace for the workflow override (ARCH §6).
const WORKFLOW_REF: &str = "refs/litany/workflow/";
/// A standing workflow mark on a conversation's descent: **who holds it**,
/// the config commit it names, and the `config/*` lineage standing exactly on
/// that commit when one does.
/// The nearest workflow mark on `agent`'s descent, or `None` — the ordinary
/// state of every agent, not an error. **An unreadable mark reads the same
/// way**, litany's own rule (*a step never fails for want of a mark it does
/// not have*): a ref that is not there and a repo that cannot answer are one
/// `None`, and the workspace that is defective is refused by the governing
/// derivation this rides beside, never by the mark. Only a git that cannot be
/// spawned at all refuses here, in its own words.