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
// SPDX-License-Identifier: MIT OR Apache-2.0
//! 2026-09-26: The serve flag surface and the lever table as one JSON document, printed by `met dump-serve-options`.
//!
//! Owner: server CLI.
//! Invariants:
//! - Every flag entry is read from `ServeArgs::command()`, and every lever entry from
//! `metrale_config::levers::all()`; nothing here lists a flag or lever by hand.
//! - A flag's `options` come from `cli::flag_values::options_for_flag`, the value sets
//! `validate_serve_args` checks against.
//!
//! `ServeArgs` has no `Serialize` derive, so the document promises no stable flag names.
//! `crate::tui::lib_fields` reads the same clap metadata for the dashboard; this adds
//! whether each flag is presence-only.
use clap::{ArgAction, CommandFactory};
use serde::Serialize;
/// 2026-09-26: Version of the document's shape: the fields of `Manifest`, `Flag` and
/// `Lever`. It does not change when a flag or lever is added or removed.
pub const SCHEMA_VERSION: u32 = 2;
/// 2026-09-26: The whole document.
#[derive(Debug, Serialize)]
pub struct Manifest {
/// 2026-09-26: `SCHEMA_VERSION`.
pub schema_version: u32,
/// 2026-09-26: `cli::METRALE_VERSION` of the binary that printed it.
pub engine_version: String,
/// 2026-09-26: Every serve flag with a long name, except clap's own help and version,
/// in `ServeArgs` declaration order.
pub flags: Vec<Flag>,
/// 2026-09-26: Every `METRALE_*` lever, from `metrale_config::levers::all()`, in name
/// order. The binary refuses to start while an undeclared `METRALE_*` variable is set
/// (`levers::check` in `main.rs`).
pub levers: Vec<Lever>,
}
/// 2026-09-26: One `METRALE_*` lever, copied from its `LeverSpec`.
#[derive(Debug, Serialize)]
pub struct Lever {
pub env: &'static str,
/// 2026-09-26: Where the setting sits in the engine's configuration: `group.name`.
pub path: &'static str,
/// 2026-09-26: `switch`, `int`, `float`, `text` or `path` (`levers::Ty::as_str`).
#[serde(rename = "type")]
pub ty: &'static str,
/// 2026-09-26: The value in force when the variable is unset, as the table states it.
pub default: &'static str,
/// 2026-09-26: The serve flag that sets the same thing and wins when given.
pub flag: Option<&'static str>,
/// 2026-09-26: `runtime`, `harness`, `build`, `dev` or `tool` (`levers::Class::as_str`).
pub class: &'static str,
/// 2026-09-26: The repository file that reads it.
pub reader: &'static str,
pub doc: &'static str,
}
/// 2026-09-26: One flag, as clap describes it.
#[derive(Debug, Serialize)]
pub struct Flag {
/// 2026-09-26: The long name with `-` replaced by `_`, the recipe `defaults:` spelling.
pub key: String,
/// 2026-09-26: The long name, without the leading dashes.
pub flag: String,
/// 2026-09-26: Whether the flag takes no value (clap `ArgAction::SetTrue`).
/// `--gdn-fused-norm` is presence-only; `--ssm-h-dtype` takes a value.
pub presence_only: bool,
/// 2026-09-26: Whether clap's value parser for the flag is the bool parser.
pub is_bool: bool,
/// 2026-09-26: The accepted values, from `cli::flag_values::options_for_flag`. Empty
/// for a free-form flag and for every bool flag.
pub options: Vec<String>,
/// 2026-09-26: clap's first default value, when it declares one.
pub default: Option<String>,
/// 2026-09-26: The first line of the flag's help.
pub help: Option<String>,
/// 2026-09-26: The flag's other long names (`get_all_aliases`), which `get_long()`
/// does not return. `--bind` has the alias `host`.
pub cli_aliases: Vec<String>,
/// 2026-09-26: Recipe keys that map to this flag under another name
/// (`recipe::schema::RENAMES`), such as `max_model_len` for `--max-seq-len`.
pub recipe_aliases: Vec<String>,
}
/// 2026-09-26: Build the document from `ServeArgs::command()` and the lever table.
#[must_use]
pub fn build() -> Manifest {
let bool_parser = clap::builder::ValueParser::bool().type_id();
let command = super::ServeArgs::command();
let flags = command
.get_arguments()
.filter_map(|arg| {
// 2026-09-26: Skip arguments without a long name (the positional MODEL) and
// clap's own help and version arguments.
let long = arg.get_long()?;
match arg.get_action() {
ArgAction::Help
| ArgAction::HelpShort
| ArgAction::HelpLong
| ArgAction::Version => return None,
_ => {}
}
let presence_only = matches!(arg.get_action(), ArgAction::SetTrue);
let is_bool = arg.get_value_parser().type_id() == bool_parser;
// 2026-09-26: A bool flag lists no values; `bool_surface_tests.rs`
// (`every_bool_flag_is_presence_only`) checks that every bool is presence-only.
let options = if is_bool {
Vec::new()
} else {
super::flag_values::options_for_flag(long).unwrap_or_default()
};
Some(Flag {
key: long.replace('-', "_"),
flag: long.to_owned(),
presence_only,
is_bool,
options,
default: arg
.get_default_values()
.first()
.map(|v| v.to_string_lossy().into_owned()),
help: arg
.get_help()
.map(|h| h.to_string().lines().next().unwrap_or_default().to_owned()),
cli_aliases: arg
.get_all_aliases()
.map(|a| a.iter().map(|s| (*s).to_owned()).collect())
.unwrap_or_default(),
recipe_aliases: crate::recipe::schema::RENAMES
.iter()
.filter(|(_, flag)| *flag == long)
.map(|(key, _)| (*key).to_owned())
.collect(),
})
})
.collect();
let levers = metrale_config::levers::all()
.map(|l| Lever {
env: l.env,
path: l.path,
ty: l.ty.as_str(),
default: l.default,
flag: l.flag,
class: l.class.as_str(),
reader: l.reader,
doc: l.doc,
})
.collect();
Manifest {
schema_version: SCHEMA_VERSION,
engine_version: super::METRALE_VERSION.to_owned(),
flags,
levers,
}
}
#[cfg(test)]
#[path = "manifest_tests.rs"]
mod tests;