1use std::path::PathBuf;
6
7use clap::{Args, Parser, Subcommand, ValueEnum};
8
9use crate::capability::builtin::Checkouts;
10
11pub const EXIT_USAGE: u8 = 2;
13
14#[derive(Debug, Parser)]
15#[command(
16 name = "majordomus",
17 version,
18 about = "Majordomus control plane: a data-driven MCP server over the repository's .ai/ layer",
19 long_about = "The Rust executable of Majordomus. It reads the repository's provider-neutral \
20AI layer under .ai/ and serves it to MCP clients over stdio. Almost every capability is a \
21query; the few that change anything declare themselves as commands and are listed by \
22`capabilities list --kind command`.\n\n\
23Most of the task lifecycle (init, start, check, finish, doctor, ...) is the shell tool \
24bin/majordomus in the same repository. Development semantics are converging onto capabilities \
25of this registry one at a time (ADR 0040); until one has, this executable does not implement \
26that command."
27)]
28pub struct Cli {
30 #[command(subcommand)]
31 pub command: Command,
33}
34
35#[derive(Debug, Subcommand)]
36pub enum Command {
38 Mcp(McpArgs),
40 Serve(ServeArgs),
42 Capabilities(CapabilitiesArgs),
44 Generate(GenerateArgs),
46 Bench(BenchArgs),
48 Scope(ScopeArgs),
50 Web(WebArgs),
52 Why(WhyArgs),
54 Devtask(DevtaskArgs),
56 Distribution(DistributionArgs),
58 Env(EnvArgs),
60 Commands(CommandsArgs),
62 Completion(CompletionArgs),
64 #[command(alias = "wt")]
66 Worktree(WorktreeArgs),
67 #[command(alias = "pr")]
69 Prs(PrsArgs),
70 Offload(OffloadArgs),
72 Convergence(ConvergenceArgs),
74 Commit(CommitArgs),
76 Product(ProductArgs),
78 Release(ReleaseArgs),
80 Quality(QualityArgs),
82 Run(RunArgs),
84 Executions(ExecutionsArgs),
86 Devcontext(DevcontextArgs),
88 Guard(GuardArgs),
90 Mesh(MeshArgs),
92 Monitor(MonitorArgs),
94 Models(ModelsArgs),
96 Reasoning(ReasoningArgs),
98 Evidence(EvidenceArgs),
100 Served(ServedArgs),
102 Rules(RulesArgs),
104 Intent(IntentArgs),
106 Delivery(DeliveryArgs),
108 Economics(EconomicsArgs),
110 Entity(EntityArgs),
112 Shell(ShellArgs),
114 Pack(PackArgs),
116 Dashboard(DashboardArgs),
118 Brief(BriefArgs),
120 Skills(SkillsArgs),
122 Knowledge(KnowledgeArgs),
124 Continuity(ContinuityArgs),
126}
127
128#[derive(Debug, Args)]
129pub struct IntentArgs {
143 #[command(flatten)]
144 pub repo: RepoArgs,
146
147 #[command(subcommand)]
148 pub command: IntentCommand,
151
152 #[arg(long, value_enum, default_value_t = OutputFormat::Text, global = true)]
153 pub format: OutputFormat,
155}
156
157#[derive(Debug, Subcommand)]
158pub enum IntentCommand {
170 List,
172 Show {
174 id: String,
176 },
177 Validate,
179 Coverage,
181 Preflight {
184 #[arg(long)]
186 issue: Option<String>,
187 #[arg(long = "path")]
189 paths: Vec<String>,
190 },
191 Binding {
195 #[arg(long)]
197 issue: Option<String>,
198 #[arg(long)]
200 intent: Option<String>,
201 #[arg(long = "path")]
203 paths: Vec<String>,
204 #[arg(long)]
206 exempt: Option<String>,
207 #[arg(long)]
209 because: Option<String>,
210 },
211 Realization {
215 #[arg(long)]
217 intent: Option<String>,
218 },
219 Explain {
221 id: String,
223 },
224 Propose {
226 #[arg(long)]
228 statement: String,
229 #[arg(long)]
231 title: Option<String>,
232 #[arg(long)]
234 id: Option<String>,
235 },
236}
237
238#[derive(Debug, Args)]
239pub struct DashboardArgs {
253 #[command(flatten)]
254 pub repo: RepoArgs,
256
257 #[command(subcommand)]
258 pub command: DashboardCommand,
260
261 #[arg(long, value_enum, default_value_t = OutputFormat::Text, global = true)]
262 pub format: OutputFormat,
264}
265
266#[derive(Debug, Args)]
267pub struct BriefArgs {
281 #[command(flatten)]
282 pub repo: RepoArgs,
284
285 #[arg(long)]
286 pub line: bool,
288
289 #[arg(long)]
290 pub keep_awake: bool,
292
293 #[arg(long, value_name = "ID")]
294 pub session: Option<String>,
296
297 #[arg(long = "this-checkout")]
298 pub this_checkout: bool,
300
301 #[arg(long, value_enum, default_value_t = OutputFormat::Text)]
302 pub format: OutputFormat,
304}
305
306#[derive(Debug, Subcommand)]
307pub enum DashboardCommand {
318 Overview,
320}
321
322#[derive(Debug, Args)]
323pub struct PackArgs {
335 #[command(flatten)]
336 pub repo: RepoArgs,
338
339 #[command(subcommand)]
340 pub command: PackCommand,
342
343 #[arg(long, value_enum, default_value_t = OutputFormat::Text, global = true)]
344 pub format: OutputFormat,
346}
347
348#[derive(Debug, Subcommand)]
349pub enum PackCommand {
360 Plan {
362 profile: Option<String>,
364 },
365 Build {
367 profile: Option<String>,
369 #[arg(long, value_name = "DIR")]
371 out: Option<PathBuf>,
372 #[arg(long)]
374 force: bool,
375 },
376 Verify {
378 dir: String,
380 },
381}
382
383#[derive(Debug, Args)]
384pub struct ShellArgs {
396 #[command(flatten)]
397 pub repo: RepoArgs,
399
400 #[command(subcommand)]
401 pub command: ShellCommand,
403
404 #[arg(long, value_enum, default_value_t = OutputFormat::Text, global = true)]
405 pub format: OutputFormat,
407}
408
409#[derive(Debug, Subcommand)]
410pub enum ShellCommand {
423 Check {
425 #[arg(long)]
427 canonical: bool,
428 },
429}
430
431#[derive(Debug, Args)]
432pub struct SkillsArgs {
451 #[command(flatten)]
452 pub repo: RepoArgs,
454
455 #[command(subcommand)]
456 pub command: SkillsCommand,
458
459 #[arg(long, value_enum, default_value_t = OutputFormat::Text, global = true)]
460 pub format: OutputFormat,
462}
463
464#[derive(Debug, Subcommand)]
465pub enum SkillsCommand {
476 Status,
478 Explain {
480 id: String,
482 },
483 Verify,
485}
486
487#[derive(Debug, Args)]
488pub struct ModelsArgs {
490 #[command(subcommand)]
491 pub command: ModelsCommand,
493}
494
495#[derive(Debug, Subcommand)]
496pub enum ModelsCommand {
498 List(ModelsListArgs),
500 Route(ModelsRouteArgs),
502}
503
504#[derive(Debug, Args)]
505pub struct ReasoningArgs {
520 #[command(flatten)]
521 pub repo: RepoArgs,
523
524 #[command(subcommand)]
525 pub command: ReasoningCommand,
527
528 #[arg(long, value_enum, default_value_t = OutputFormat::Text, global = true)]
529 pub format: OutputFormat,
531}
532
533#[derive(Debug, Subcommand)]
534pub enum ReasoningCommand {
553 Advisors,
555 Plan {
557 #[arg(long, default_value = "material")]
559 materiality: String,
560 #[arg(long, default_value = "medium")]
562 confidence: String,
563 #[arg(long)]
565 capabilities: Option<String>,
566 },
567 Record {
569 #[arg(long)]
571 file: Option<std::path::PathBuf>,
572 },
573 Status {
575 #[arg(long)]
577 task: Option<String>,
578 #[arg(long)]
580 report: bool,
581 },
582 Explain {
584 id: String,
586 },
587 Check,
589}
590
591#[derive(Debug, Args)]
592pub struct ModelsListArgs {
594 #[command(flatten)]
595 pub repo: RepoArgs,
597
598 #[arg(long)]
599 pub vendor: Option<String>,
601
602 #[arg(long)]
603 pub capability: Option<String>,
605
606 #[arg(long)]
607 pub id: Option<String>,
609
610 #[arg(long, value_enum, default_value_t = OutputFormat::Text)]
611 pub format: OutputFormat,
613}
614
615#[derive(Debug, Args)]
616pub struct ModelsRouteArgs {
618 #[command(flatten)]
619 pub repo: RepoArgs,
621
622 #[arg(long)]
623 pub require: Option<String>,
625
626 #[arg(long)]
627 pub min_context: Option<u64>,
629
630 #[arg(long)]
631 pub vendor: Option<String>,
633
634 #[arg(long)]
635 pub local_only: bool,
637
638 #[arg(long)]
639 pub model: Option<String>,
641
642 #[arg(long, value_enum, default_value_t = OutputFormat::Text)]
643 pub format: OutputFormat,
645}
646
647#[derive(Debug, Args)]
648pub struct GuardArgs {
663 #[command(subcommand)]
664 pub command: GuardCommand,
666}
667
668#[derive(Debug, Subcommand)]
669pub enum GuardCommand {
682 Hook(GuardHookArgs),
684}
685
686#[derive(Debug, Args)]
687pub struct GuardHookArgs {
700 #[arg(long, default_value = "claude-code")]
702 pub provider: String,
703 #[arg(long, value_name = "PATH")]
705 pub repo: Option<PathBuf>,
706}
707
708#[derive(Debug, Args)]
709pub struct MeshArgs {
711 #[command(subcommand)]
712 pub command: MeshCommand,
714}
715
716#[derive(Debug, Subcommand)]
717pub enum MeshCommand {
719 Status(MeshQueryArgs),
721 Nodes(MeshQueryArgs),
723 Identity(MeshQueryArgs),
725 Doctor(MeshQueryArgs),
727 Firewall(MeshFirewallArgs),
729 Peers(MeshViewArgs),
731 Peer(MeshPeerArgs),
733 State(MeshViewArgs),
735 Events(MeshEventsArgs),
737 Verify(MeshQueryArgs),
739 Claim(MeshClaimArgs),
741 Release(MeshReleaseArgs),
743 Session(MeshSessionArgs),
745 Handover(MeshHandoverArgs),
747 Review(MeshReviewArgs),
749}
750
751#[derive(Debug, Args)]
752pub struct MeshFirewallArgs {
776 #[command(subcommand)]
777 pub command: Option<MeshFirewallCommand>,
779 #[arg(long)]
780 pub port: Option<u16>,
782 #[command(flatten)]
783 pub query: MeshQueryArgs,
785}
786
787#[derive(Debug, Subcommand)]
788pub enum MeshFirewallCommand {
806 Apply(MeshFirewallApplyArgs),
808}
809
810#[derive(Debug, Args)]
811pub struct MeshFirewallApplyArgs {
828 #[arg(long)]
829 pub port: Option<u16>,
831 #[command(flatten)]
832 pub query: MeshQueryArgs,
834}
835
836#[derive(Debug, Args)]
837pub struct MeshPeerArgs {
856 pub runtime: String,
858 #[command(flatten)]
859 pub query: MeshQueryArgs,
861}
862
863#[derive(Debug, Args)]
864pub struct MeshEventsArgs {
896 #[arg(long)]
898 pub after: Option<u64>,
899 #[arg(long)]
901 pub limit: Option<u64>,
902 #[arg(long)]
904 pub newest: bool,
905 #[command(flatten)]
906 pub query: MeshQueryArgs,
908}
909
910#[derive(Debug, Args)]
911pub struct MeshViewArgs {
936 #[arg(long)]
938 pub full: bool,
939 #[arg(long)]
941 pub live_claims: bool,
942 #[arg(long)]
944 pub after: Option<u64>,
945 #[arg(long)]
947 pub session: Option<String>,
948 #[arg(long)]
950 pub runtime: Option<String>,
951 #[arg(long)]
953 pub kind: Option<String>,
954 #[arg(long)]
956 pub limit: Option<usize>,
957 #[arg(long)]
959 pub open: bool,
960 #[arg(long)]
962 pub matching: Option<String>,
963 #[command(flatten)]
964 pub query: MeshQueryArgs,
966}
967
968impl MeshViewArgs {
969 pub fn pairs(&self) -> Vec<String> {
983 let mut pairs = Vec::new();
984 if self.full {
985 pairs.push("view=full".to_string());
986 }
987 if self.live_claims {
988 pairs.push("claims=live".to_string());
989 }
990 if let Some(after) = self.after {
991 pairs.push(format!("after={after}"));
992 }
993 if let Some(session) = &self.session {
994 pairs.push(format!("session={session}"));
995 }
996 if let Some(runtime) = &self.runtime {
997 pairs.push(format!("runtime={runtime}"));
998 }
999 if let Some(kind) = &self.kind {
1000 pairs.push(format!("kind={kind}"));
1001 }
1002 if let Some(limit) = self.limit {
1003 pairs.push(format!("limit={limit}"));
1004 }
1005 if self.open {
1006 pairs.push("open=true".to_string());
1007 }
1008 if let Some(text) = &self.matching {
1009 pairs.push(format!("matching={text}"));
1010 }
1011 pairs
1012 }
1013}
1014
1015#[derive(Debug, Args)]
1016pub struct MeshClaimArgs {
1041 #[arg(required = true)]
1043 pub scope: Vec<String>,
1044 #[arg(long)]
1046 pub session: String,
1047 #[arg(long)]
1049 pub intent: Option<String>,
1050 #[arg(long)]
1052 pub advisory: bool,
1053 #[arg(long)]
1055 pub issue: Option<String>,
1056 #[arg(long)]
1058 pub task: Option<String>,
1059 #[command(flatten)]
1060 pub query: MeshQueryArgs,
1062}
1063
1064#[derive(Debug, Args)]
1065pub struct MeshReleaseArgs {
1084 pub claim: String,
1086 #[command(flatten)]
1087 pub query: MeshQueryArgs,
1089}
1090
1091#[derive(Debug, Args)]
1092pub struct MeshSessionArgs {
1111 #[command(subcommand)]
1112 pub command: MeshSessionCommand,
1114}
1115
1116#[derive(Debug, Subcommand)]
1117pub enum MeshSessionCommand {
1136 Open(MeshSessionOpenArgs),
1138 Close(MeshSessionCloseArgs),
1140}
1141
1142#[derive(Debug, Args)]
1143pub struct MeshSessionOpenArgs {
1172 #[arg(long)]
1174 pub session: String,
1175 #[arg(long)]
1177 pub client: Option<String>,
1178 #[arg(long)]
1180 pub worker: Option<String>,
1181 #[arg(long)]
1183 pub intent: Option<String>,
1184 #[arg(long)]
1186 pub task: Option<String>,
1187 #[arg(long)]
1189 pub issue: Option<String>,
1190 #[arg(long)]
1192 pub milestone: Option<String>,
1193 #[arg(long)]
1195 pub branch: Option<String>,
1196 #[arg(long)]
1198 pub head: Option<String>,
1199 #[command(flatten)]
1200 pub query: MeshQueryArgs,
1202}
1203
1204#[derive(Debug, Args)]
1205pub struct MeshSessionCloseArgs {
1225 #[arg(long)]
1227 pub session: String,
1228 #[command(flatten)]
1229 pub query: MeshQueryArgs,
1231}
1232
1233#[derive(Debug, Args)]
1234pub struct MeshHandoverArgs {
1252 #[command(subcommand)]
1253 pub command: MeshHandoverCommand,
1255}
1256
1257#[derive(Debug, Subcommand)]
1258pub enum MeshHandoverCommand {
1278 Publish(MeshHandoverPublishArgs),
1280 Consume(MeshHandoverConsumeArgs),
1282}
1283
1284#[derive(Debug, Args)]
1285pub struct MeshHandoverPublishArgs {
1308 #[arg(long)]
1310 pub path: Option<String>,
1311 #[arg(long)]
1313 pub issue: Option<String>,
1314 #[arg(long)]
1316 pub milestone: Option<String>,
1317 #[command(flatten)]
1318 pub query: MeshQueryArgs,
1320}
1321
1322#[derive(Debug, Args)]
1323pub struct MeshHandoverConsumeArgs {
1350 pub handover: String,
1352 #[arg(long)]
1354 pub session: String,
1355 #[arg(long)]
1357 pub no_materialize: bool,
1358 #[command(flatten)]
1359 pub query: MeshQueryArgs,
1361}
1362
1363#[derive(Debug, Args)]
1364pub struct MeshReviewArgs {
1386 #[command(subcommand)]
1387 pub command: MeshReviewCommand,
1389}
1390
1391#[derive(Debug, Subcommand)]
1392pub enum MeshReviewCommand {
1412 Request(MeshReviewRequestArgs),
1414 Answer(MeshReviewAnswerArgs),
1416 Withdraw(MeshReviewWithdrawArgs),
1418}
1419
1420#[derive(Debug, Args)]
1421pub struct MeshReviewRequestArgs {
1446 pub subject: String,
1448 #[arg(long)]
1450 pub session: String,
1451 #[arg(long)]
1453 pub scope: Vec<String>,
1454 #[arg(long)]
1456 pub issue: Option<String>,
1457 #[arg(long)]
1459 pub reviewer: Option<String>,
1460 #[arg(long)]
1463 pub body: Option<String>,
1464 #[command(flatten)]
1465 pub query: MeshQueryArgs,
1467}
1468
1469#[derive(Debug, Args)]
1470pub struct MeshReviewAnswerArgs {
1500 pub request: String,
1502 #[arg(long)]
1504 pub session: String,
1505 #[arg(long, value_parser = [
1507 clap::builder::PossibleValue::new("approved")
1508 .help("the work is good as it stands and the requester may proceed"),
1509 clap::builder::PossibleValue::new("changes_requested")
1510 .help("the work needs changing before it proceeds; the note says what"),
1511 clap::builder::PossibleValue::new("commented")
1512 .help("an observation with no verdict: neither approval nor a request to change"),
1513 ])]
1514 pub verdict: String,
1515 #[arg(long)]
1517 pub note: Option<String>,
1518 #[command(flatten)]
1519 pub query: MeshQueryArgs,
1521}
1522
1523#[derive(Debug, Args)]
1524pub struct MonitorArgs {
1549 #[arg(long)]
1551 pub follow: bool,
1552 #[arg(long)]
1554 pub after: Option<String>,
1555 #[arg(long)]
1557 pub limit: Option<u64>,
1558 #[arg(long)]
1560 pub sources: Option<String>,
1561 #[arg(long = "for")]
1563 pub reader: Option<String>,
1564 #[arg(long, value_parser = parse_duration)]
1566 pub since: Option<u64>,
1567 #[arg(long = "match")]
1569 pub pattern: Option<String>,
1570 #[arg(long)]
1572 pub count: Option<u64>,
1573 #[arg(long)]
1575 pub until: Option<String>,
1576 #[arg(long, value_parser = parse_duration)]
1578 pub timeout: Option<u64>,
1579 #[arg(long, default_value_t = 2)]
1581 pub interval: u64,
1582 #[command(flatten)]
1583 pub query: MeshQueryArgs,
1585}
1586
1587pub fn parse_duration(text: &str) -> std::result::Result<u64, String> {
1599 let text = text.trim();
1600 let (number, unit) = match text.char_indices().last() {
1601 Some((i, c)) if c.is_ascii_alphabetic() => (&text[..i], c),
1602 _ => (text, 's'),
1603 };
1604 let n: u64 = number
1605 .parse()
1606 .map_err(|_| format!("{text:?} is not a duration: write 90, 90s, 30m, 2h or 1d"))?;
1607 let scale = match unit {
1608 's' => 1,
1609 'm' => 60,
1610 'h' => 3600,
1611 'd' => 86400,
1612 _ => return Err(format!("{text:?} has an unknown unit: use s, m, h or d")),
1613 };
1614 Ok(n.saturating_mul(scale))
1615}
1616
1617#[derive(Debug, Args)]
1618pub struct MeshReviewWithdrawArgs {
1640 pub request: String,
1642 #[arg(long)]
1644 pub session: String,
1645 #[arg(long)]
1647 pub note: Option<String>,
1648 #[command(flatten)]
1649 pub query: MeshQueryArgs,
1651}
1652
1653#[derive(Debug, Args)]
1654pub struct MeshQueryArgs {
1656 #[command(flatten)]
1657 pub repo: RepoArgs,
1659
1660 #[arg(long, value_enum, default_value_t = OutputFormat::Text)]
1661 pub format: OutputFormat,
1663}
1664
1665#[derive(Debug, Args)]
1666pub struct ProductArgs {
1669 #[command(flatten)]
1670 pub repo: RepoArgs,
1672
1673 #[command(subcommand)]
1674 pub command: Option<ProductCommand>,
1676
1677 #[arg(long, value_enum, default_value_t = OutputFormat::Text, global = true)]
1678 pub format: OutputFormat,
1680
1681 #[arg(long, global = true)]
1683 pub featured: bool,
1684 #[arg(long, global = true)]
1686 pub all: bool,
1687 #[arg(long, global = true)]
1689 pub area: Option<String>,
1690 #[arg(long, global = true)]
1692 pub domain: Option<String>,
1693 #[arg(long, global = true)]
1695 pub module: Option<String>,
1696 #[arg(long = "names-command", global = true)]
1698 pub names_command: Option<String>,
1699 #[arg(long, global = true)]
1701 pub surface: Option<String>,
1702 #[arg(long, short = 'q', global = true)]
1704 pub query: Option<String>,
1705}
1706
1707#[derive(Debug, Subcommand)]
1708pub enum ProductCommand {
1710 List,
1712 Show {
1714 id: String,
1716 },
1717 Domains,
1719 Matrix,
1721 Providers,
1723 Validate,
1725}
1726
1727#[derive(Debug, Args)]
1728pub struct EnvArgs {
1730 #[command(flatten)]
1731 pub repo: RepoArgs,
1733
1734 #[command(subcommand)]
1735 pub command: Option<EnvCommand>,
1737
1738 #[arg(long, value_enum, default_value_t = OutputFormat::Text, global = true)]
1739 pub format: OutputFormat,
1741}
1742
1743#[derive(Debug, Subcommand)]
1744pub enum EnvCommand {
1746 Status,
1748 Banner {
1750 #[arg(long, value_name = "MODE")]
1752 mode: Option<String>,
1753 #[arg(long, value_name = "COLUMNS")]
1755 width: Option<usize>,
1756 },
1757 Export {
1759 #[arg(long = "shell", value_name = "SHELL", default_value = "direnv")]
1761 shell: String,
1762 #[arg(long)]
1764 banner: bool,
1765 #[arg(long, value_name = "MODE", requires = "banner")]
1767 mode: Option<String>,
1768 #[arg(long)]
1770 bridge: bool,
1771 },
1772 Enter {
1774 #[arg(long = "shell", value_name = "SHELL", default_value = "direnv")]
1776 shell: String,
1777 #[arg(long, value_name = "MODE", conflicts_with = "no_banner")]
1779 mode: Option<String>,
1780 #[arg(long = "no-banner")]
1782 no_banner: bool,
1783 #[arg(long = "no-bridge")]
1785 no_bridge: bool,
1786 #[arg(long = "no-runtime")]
1788 no_runtime: bool,
1789 #[arg(long, value_name = "SECONDS", default_value_t = 0)]
1791 wait: u64,
1792 },
1793 Explain {
1795 #[arg(value_name = "FIELD")]
1797 field: Option<String>,
1798 },
1799 Preflight {
1801 #[arg(long)]
1803 compact: bool,
1804 #[arg(long)]
1806 full: bool,
1807 },
1808}
1809
1810#[derive(Debug, Args)]
1811pub struct ReleaseArgs {
1814 #[command(flatten)]
1815 pub repo: RepoArgs,
1817
1818 #[command(subcommand)]
1819 pub command: Option<ReleaseCommand>,
1821
1822 #[arg(long, value_enum, default_value_t = OutputFormat::Text, global = true)]
1823 pub format: OutputFormat,
1825}
1826
1827#[derive(Debug, Subcommand)]
1828pub enum ReleaseCommand {
1830 Changelog {
1832 #[arg(value_name = "VERSION")]
1834 version: Option<String>,
1835 },
1836 Version,
1838 Analyze {
1840 #[arg(long, value_name = "REF")]
1842 since: Option<String>,
1843 #[arg(long)]
1845 explain: bool,
1846 },
1847 Next {
1849 #[arg(long, value_name = "REF", default_value = "origin/master")]
1851 base: String,
1852 #[arg(long, value_name = "REF", default_value = "HEAD")]
1854 head: String,
1855 },
1856 Bump {
1858 #[arg(long, value_name = "LEVEL")]
1860 level: Option<String>,
1861 #[arg(long, value_name = "VERSION", conflicts_with = "level")]
1863 exact: Option<String>,
1864 #[arg(long)]
1866 dry_run: bool,
1867 },
1868}
1869
1870#[derive(Debug, Args)]
1871pub struct QualityArgs {
1875 #[command(subcommand)]
1876 pub command: QualityCommand,
1878}
1879
1880#[derive(Debug, Subcommand)]
1881pub enum QualityCommand {
1883 Report(QualityReportArgs),
1885 Rustdoc(QualityRustdocArgs),
1887}
1888
1889#[derive(Debug, Args)]
1890pub struct QualityRustdocArgs {
1919 #[command(flatten)]
1920 pub repo: RepoArgs,
1922
1923 #[arg(long, value_enum, default_value_t = OutputFormat::Text)]
1924 pub format: OutputFormat,
1926
1927 #[arg(long)]
1929 pub kind: Option<String>,
1930
1931 #[arg(long)]
1933 pub summary: bool,
1934
1935 #[arg(long, value_name = "DIR")]
1937 pub tree: Option<std::path::PathBuf>,
1938}
1939
1940#[derive(Debug, Args)]
1941pub struct ConvergenceArgs {
1963 #[command(flatten)]
1964 pub repo: RepoArgs,
1966
1967 #[arg(long, value_enum, default_value_t = OutputFormat::Text)]
1968 pub format: OutputFormat,
1970
1971 #[arg(long)]
1972 pub all: bool,
1974}
1975
1976#[derive(Debug, Args)]
1977pub struct QualityReportArgs {
1979 #[command(flatten)]
1980 pub repo: RepoArgs,
1982
1983 #[arg(long, value_enum, default_value_t = OutputFormat::Text)]
1984 pub format: OutputFormat,
1986
1987 #[arg(long)]
1989 pub code: Option<String>,
1990
1991 #[arg(long)]
1993 pub path: Option<String>,
1994
1995 #[arg(long)]
1997 pub summary: bool,
1998
1999 #[arg(long)]
2001 pub include_baselined: bool,
2002
2003 #[arg(long)]
2005 pub write_baseline: bool,
2006}
2007
2008#[derive(Debug, Args)]
2009pub struct EconomicsArgs {
2028 #[command(subcommand)]
2029 pub command: EconomicsCommand,
2031}
2032
2033#[derive(Debug, Subcommand)]
2034pub enum EconomicsCommand {
2060 Summary(EconomicsSummaryArgs),
2062 Explain(EconomicsExplainArgs),
2064 Runs(EconomicsRunsArgs),
2066 Check(EconomicsCheckArgs),
2068 Measure(EconomicsMeasureArgs),
2070 Run(EconomicsRunArgs),
2072 References(EconomicsReferencesArgs),
2074}
2075
2076#[derive(Debug, Args)]
2077pub struct EconomicsSummaryArgs {
2106 #[command(flatten)]
2107 pub repo: RepoArgs,
2109 #[arg(long, value_enum, default_value_t = OutputFormat::Text)]
2110 pub format: OutputFormat,
2112 #[arg(long)]
2114 pub suite: Option<String>,
2115 #[arg(long)]
2117 pub category: Option<String>,
2118 #[arg(long)]
2120 pub task: Option<String>,
2121 #[arg(long)]
2123 pub model: Option<String>,
2124}
2125
2126#[derive(Debug, Args)]
2127pub struct EconomicsExplainArgs {
2151 #[command(flatten)]
2152 pub repo: RepoArgs,
2154 #[arg(long, value_enum, default_value_t = OutputFormat::Text)]
2155 pub format: OutputFormat,
2157 pub metric: String,
2159}
2160
2161#[derive(Debug, Args)]
2162pub struct EconomicsRunsArgs {
2185 #[command(flatten)]
2186 pub repo: RepoArgs,
2188 #[arg(long, value_enum, default_value_t = OutputFormat::Text)]
2189 pub format: OutputFormat,
2191 #[arg(long)]
2193 pub suite: Option<String>,
2194 #[arg(long)]
2196 pub task: Option<String>,
2197 #[arg(long)]
2199 pub variant: Option<String>,
2200}
2201
2202#[derive(Debug, Args)]
2203pub struct EconomicsCheckArgs {
2226 #[command(flatten)]
2227 pub repo: RepoArgs,
2229 #[arg(long, value_enum, default_value_t = OutputFormat::Text)]
2230 pub format: OutputFormat,
2232}
2233
2234#[derive(Debug, Args)]
2235pub struct EconomicsMeasureArgs {
2258 #[command(flatten)]
2259 pub repo: RepoArgs,
2261 #[arg(long, default_value = "context")]
2263 pub suite: String,
2264 #[arg(long)]
2266 pub dry_run: bool,
2267}
2268
2269#[derive(Debug, Args)]
2270pub struct EconomicsRunArgs {
2303 #[command(flatten)]
2304 pub repo: RepoArgs,
2306 #[arg(long, default_value = "pilot")]
2308 pub suite: String,
2309 #[arg(long = "task")]
2311 pub tasks: Vec<String>,
2312 #[arg(long = "repetition")]
2314 pub repetitions: Vec<u32>,
2315 #[arg(long, value_name = "PATH")]
2318 pub work_dir: Option<PathBuf>,
2319 #[arg(long, value_name = "PATH", default_value = "claude")]
2321 pub harness: PathBuf,
2322 #[arg(long, default_value_t = 2)]
2324 pub parallel: usize,
2325 #[arg(long, default_value_t = 1800)]
2327 pub session_timeout: u64,
2328 #[arg(long)]
2331 pub force: bool,
2332 #[arg(long)]
2334 pub dry_run: bool,
2335}
2336
2337#[derive(Debug, Args)]
2338pub struct EconomicsReferencesArgs {
2363 #[command(flatten)]
2364 pub repo: RepoArgs,
2366 #[arg(long, value_name = "PATH")]
2368 pub work_dir: Option<PathBuf>,
2369}
2370
2371#[derive(Debug, Args)]
2372pub struct RunArgs {
2380 #[command(flatten)]
2381 pub repo: RepoArgs,
2383
2384 pub capability: String,
2386
2387 #[arg(long, value_name = "JSON")]
2389 pub input: Option<String>,
2390
2391 #[arg(long)]
2393 pub follow: bool,
2394
2395 #[arg(long)]
2397 pub quiet: bool,
2398
2399 #[arg(long, value_enum, default_value_t = OutputFormat::Text)]
2400 pub format: OutputFormat,
2402}
2403
2404#[derive(Debug, Args)]
2405pub struct ExecutionsArgs {
2411 #[command(flatten)]
2412 pub repo: RepoArgs,
2414
2415 #[command(subcommand)]
2416 pub command: Option<ExecutionsCommand>,
2418
2419 #[arg(long, value_enum, default_value_t = OutputFormat::Text, global = true)]
2420 pub format: OutputFormat,
2422}
2423
2424#[derive(Debug, Subcommand)]
2425pub enum ExecutionsCommand {
2427 List {
2429 #[arg(long)]
2431 state: Option<String>,
2432 #[arg(long)]
2434 capability: Option<String>,
2435 },
2436 Show {
2438 id: String,
2440 },
2441 Events {
2443 id: String,
2445 #[arg(long)]
2447 after: Option<u64>,
2448 },
2449 Cancel {
2451 id: String,
2453 },
2454 Protocol,
2456}
2457
2458#[derive(Debug, Args)]
2459pub struct EvidenceArgs {
2483 #[command(flatten)]
2484 pub repo: RepoArgs,
2486
2487 #[command(subcommand)]
2488 pub command: EvidenceCommand,
2492
2493 #[arg(long, value_enum, default_value_t = OutputFormat::Text, global = true)]
2494 pub format: OutputFormat,
2496}
2497
2498#[derive(Debug, Subcommand)]
2499pub enum EvidenceCommand {
2557 Show {
2559 #[arg(long)]
2561 state: Option<String>,
2562 #[arg(long)]
2564 status: Option<String>,
2565 #[arg(long)]
2567 findings: bool,
2568 #[arg(long)]
2570 check: bool,
2571 #[arg(long, value_name = "REV")]
2573 presented: Option<String>,
2574 #[arg(
2576 long,
2577 value_name = "TREE",
2578 value_parser = clap::builder::PossibleValuesParser::new([
2579 clap::builder::PossibleValue::new("clean")
2580 .help("Nothing you know of: the measured state stands"),
2581 clap::builder::PossibleValue::new("dirty")
2582 .help("The build did not come from the commit as committed; nothing reads as proven"),
2583 clap::builder::PossibleValue::new("unknown")
2584 .help("You cannot say whether it did; nothing reads as proven"),
2585 ])
2586 )]
2587 presented_tree: Option<String>,
2588 },
2589 Claim {
2591 id: String,
2593 },
2594 Proves {
2596 id: String,
2598 },
2599 Record {
2601 #[arg(long)]
2603 suite: Option<PathBuf>,
2604 #[arg(long)]
2606 crate_output: Option<PathBuf>,
2607 #[arg(long)]
2609 origin: Option<String>,
2610 #[arg(long, value_name = "[PRODUCER=]FILE")]
2613 provenance: Vec<String>,
2614 #[arg(long)]
2616 coverage: Option<PathBuf>,
2617 #[arg(long)]
2619 ledger: Option<String>,
2620 #[arg(long)]
2622 run_record: Option<PathBuf>,
2623 },
2624 Stamp {
2626 #[arg(long)]
2628 producer: Option<String>,
2629 #[arg(long)]
2631 report: Option<PathBuf>,
2632 #[arg(long)]
2634 exclude: Vec<String>,
2635 #[arg(long)]
2637 out: Option<PathBuf>,
2638 },
2639}
2640
2641#[derive(Debug, Args)]
2642pub struct DeliveryArgs {
2662 #[command(flatten)]
2663 pub repo: RepoArgs,
2665
2666 #[command(subcommand)]
2667 pub command: DeliveryCommand,
2669
2670 #[arg(long, value_enum, default_value_t = OutputFormat::Text, global = true)]
2671 pub format: OutputFormat,
2673}
2674
2675#[derive(Debug, Subcommand)]
2676pub enum DeliveryCommand {
2697 Report {
2699 #[arg(long)]
2701 check: bool,
2702 },
2703 Show {
2705 id: String,
2707 #[arg(long)]
2709 check: bool,
2710 },
2711}
2712
2713#[derive(Debug, Args)]
2714pub struct ServedArgs {
2741 #[command(flatten)]
2742 pub repo: RepoArgs,
2744
2745 #[command(subcommand)]
2746 pub command: ServedCommand,
2748
2749 #[arg(long, value_enum, default_value_t = OutputFormat::Text, global = true)]
2750 pub format: OutputFormat,
2752}
2753
2754#[derive(Debug, Subcommand)]
2755pub enum ServedCommand {
2770 Observe {
2772 #[arg(long)]
2774 commit: Option<String>,
2775 #[arg(long)]
2777 url: Option<String>,
2778 #[arg(long)]
2780 identity: Option<String>,
2781 #[arg(long)]
2783 deployment: Option<String>,
2784 #[arg(long)]
2786 timeout: Option<u64>,
2787 #[arg(long)]
2789 dry_run: bool,
2790 },
2791 Forge,
2793 Show {
2795 #[arg(long)]
2797 commit: Option<String>,
2798 #[arg(long)]
2800 deployment: Option<String>,
2801 },
2802}
2803
2804#[derive(Debug, Args)]
2805pub struct EntityArgs {
2820 #[command(flatten)]
2821 pub repo: RepoArgs,
2823
2824 #[command(subcommand)]
2825 pub command: EntityCommand,
2828
2829 #[arg(long, value_enum, default_value_t = OutputFormat::Text, global = true)]
2830 pub format: OutputFormat,
2832}
2833
2834#[derive(Debug, Subcommand)]
2835pub enum EntityCommand {
2846 Kinds,
2848 Show {
2850 address: String,
2852 },
2853}
2854
2855#[derive(Debug, Args)]
2856pub struct RulesArgs {
2872 #[command(flatten)]
2873 pub repo: RepoArgs,
2875
2876 #[command(subcommand)]
2877 pub command: RulesCommand,
2881
2882 #[arg(long, value_enum, default_value_t = OutputFormat::Text, global = true)]
2883 pub format: OutputFormat,
2885}
2886
2887#[derive(Debug, Subcommand)]
2888pub enum RulesCommand {
2899 Report {
2901 #[arg(long)]
2903 state: Option<String>,
2904 #[arg(long)]
2906 class: Option<String>,
2907 #[arg(long)]
2909 namespace: Option<String>,
2910 #[arg(long)]
2912 findings: bool,
2913 #[arg(long)]
2915 check: bool,
2916 },
2917 Show {
2919 id: String,
2921 },
2922 Proves {
2924 id: String,
2926 },
2927}
2928
2929#[derive(Debug, Args)]
2930pub struct KnowledgeArgs {
2945 #[command(flatten)]
2946 pub repo: RepoArgs,
2948
2949 #[command(subcommand)]
2950 pub command: KnowledgeCommand,
2954
2955 #[arg(long, value_enum, default_value_t = OutputFormat::Text, global = true)]
2956 pub format: OutputFormat,
2958}
2959
2960#[derive(Debug, Subcommand)]
2961pub enum KnowledgeCommand {
2973 Candidates,
2975 Record {
2977 id: String,
2979 },
2980 Status,
2982}
2983
2984#[derive(Debug, Args)]
2985pub struct ContinuityArgs {
3000 #[command(flatten)]
3001 pub repo: RepoArgs,
3003
3004 #[command(subcommand)]
3005 pub command: ContinuityCommand,
3008
3009 #[arg(long, value_enum, default_value_t = OutputFormat::Text, global = true)]
3010 pub format: OutputFormat,
3012}
3013
3014#[derive(Debug, Subcommand)]
3015pub enum ContinuityCommand {
3029 Status,
3031 Records,
3033 Device {
3035 #[arg(long)]
3037 label: Option<String>,
3038 },
3039 Plan {
3041 #[arg(long)]
3043 record: Option<String>,
3044 },
3045 Publish {
3047 #[arg(long)]
3049 handover: Option<String>,
3050 #[arg(long)]
3052 issue: Option<String>,
3053 #[arg(long)]
3055 milestone: Option<String>,
3056 },
3057 Sync {
3059 #[arg(long)]
3061 remote: Option<String>,
3062 },
3063 Resume {
3065 #[arg(long)]
3067 record: Option<String>,
3068 },
3069}
3070
3071#[derive(Debug, Args)]
3072pub struct WhyArgs {
3075 #[command(flatten)]
3076 pub repo: RepoArgs,
3078
3079 #[command(subcommand)]
3080 pub command: Option<WhyCommand>,
3082
3083 #[arg(long, value_enum, default_value_t = OutputFormat::Text, global = true)]
3084 pub format: OutputFormat,
3086
3087 #[arg(long, global = true)]
3089 pub audience: Option<String>,
3090 #[arg(long, global = true)]
3092 pub area: Option<String>,
3093 #[arg(long, global = true)]
3095 pub tag: Option<String>,
3096 #[arg(long, global = true)]
3098 pub severity: Option<String>,
3099 #[arg(long, global = true)]
3101 pub frequency: Option<String>,
3102 #[arg(long, global = true)]
3104 pub lifecycle: Option<String>,
3105 #[arg(long, global = true)]
3107 pub capability: Option<String>,
3108 #[arg(long = "names-command", global = true)]
3110 pub names_command: Option<String>,
3111 #[arg(long, global = true)]
3113 pub featured: bool,
3114 #[arg(long, global = true)]
3116 pub all: bool,
3117 #[arg(long, short = 'q', global = true)]
3119 pub query: Option<String>,
3120}
3121
3122#[derive(Debug, Subcommand)]
3123pub enum WhyCommand {
3125 List,
3127 Show {
3129 id: String,
3131 },
3132 Audiences,
3134 Areas,
3136 Diagnose {
3138 #[arg(long = "signal")]
3140 signals: Vec<String>,
3141 },
3142 Validate,
3144}
3145
3146#[derive(Debug, Args)]
3147pub struct DevtaskArgs {
3150 #[command(flatten)]
3151 pub repo: RepoArgs,
3153
3154 #[command(subcommand)]
3155 pub command: DevtaskCommand,
3157
3158 #[arg(long, value_enum, default_value_t = OutputFormat::Text, global = true)]
3159 pub format: OutputFormat,
3161}
3162
3163#[derive(Debug, Subcommand)]
3164pub enum DevtaskCommand {
3166 Issue {
3168 id: String,
3170 #[arg(long = "no-git")]
3172 no_git: bool,
3173 },
3174 Milestone {
3176 id: String,
3178 },
3179}
3180
3181#[derive(Debug, Args)]
3182pub struct DistributionArgs {
3184 #[command(flatten)]
3185 pub repo: RepoArgs,
3187
3188 #[command(subcommand)]
3189 pub command: Option<DistributionCommand>,
3191
3192 #[arg(long, value_enum, default_value_t = OutputFormat::Text, global = true)]
3193 pub format: OutputFormat,
3195}
3196
3197#[derive(Debug, Subcommand)]
3198pub enum DistributionCommand {
3200 Show,
3202 Status,
3204 Validate,
3206 Targets,
3208 Matrix,
3210 Artifact {
3212 #[arg(long, value_name = "TARGET")]
3214 target: String,
3215 #[arg(long, value_name = "TAG")]
3217 tag: String,
3218 },
3219 Releases,
3221 Metadata {
3223 #[arg(long, value_name = "FILE")]
3225 record: PathBuf,
3226 },
3227 Build,
3229}
3230
3231#[derive(Debug, Args)]
3232pub struct WebArgs {
3234 #[command(flatten)]
3235 pub repo: RepoArgs,
3237
3238 #[command(subcommand)]
3239 pub command: Option<WebCommand>,
3241
3242 #[arg(long, value_enum, default_value_t = OutputFormat::Text, global = true)]
3243 pub format: OutputFormat,
3245
3246 #[arg(long, value_delimiter = ',', global = true)]
3248 pub only: Vec<String>,
3249
3250 #[arg(long, value_delimiter = ',', global = true)]
3252 pub exclude: Vec<String>,
3253}
3254
3255#[derive(Debug, Subcommand)]
3256pub enum ReportCommand {
3259 Tests {
3261 #[arg(long)]
3263 suite: PathBuf,
3264 #[arg(long)]
3266 crate_output: Option<PathBuf>,
3267 },
3268 Benchmarks {
3270 #[arg(long)]
3272 from: PathBuf,
3273 },
3274 Ui {
3276 #[arg(long)]
3278 from: PathBuf,
3279 },
3280 UiSnapshot {
3283 #[arg(long, default_value_t = crate::web::report::snapshot::DEFAULT_LIMIT)]
3285 limit: usize,
3286 #[arg(long, default_value_t = crate::web::report::snapshot::DEFAULT_BUDGET_SECONDS)]
3289 budget_seconds: u64,
3290 },
3291 CockpitSnapshot {
3294 #[arg(long, default_value_t = crate::web::report::snapshot::DEFAULT_LIMIT)]
3297 limit: usize,
3298 #[arg(long, default_value_t = crate::web::report::snapshot::DEFAULT_BUDGET_SECONDS)]
3301 budget_seconds: u64,
3302 },
3303}
3304
3305#[derive(Debug, Subcommand)]
3306pub enum WebCommand {
3308 List,
3310 Explain {
3312 id: Option<String>,
3314 },
3315 Validate {
3317 #[arg(long)]
3319 artifacts: bool,
3320 },
3321 Manifest,
3323 Report {
3325 #[command(subcommand)]
3326 report: ReportCommand,
3328 },
3329 Compose {
3331 #[arg(long)]
3333 destination: Option<String>,
3334 },
3335}
3336
3337#[derive(Debug, Args)]
3338pub struct ScopeArgs {
3340 #[command(flatten)]
3341 pub repo: RepoArgs,
3343
3344 pub paths: Vec<String>,
3346
3347 #[arg(long, value_enum, default_value_t = OutputFormat::Text)]
3348 pub format: OutputFormat,
3350
3351 #[arg(long)]
3353 pub check: bool,
3354}
3355
3356#[derive(Debug, Args)]
3357#[command(args_conflicts_with_subcommands = true)]
3358pub struct BenchArgs {
3360 #[command(flatten)]
3361 pub repo: RepoArgs,
3363
3364 #[command(subcommand)]
3365 pub command: Option<BenchCommand>,
3367
3368 pub id: Option<String>,
3370
3371 #[arg(long, value_enum, default_value_t = TransportArg::All)]
3373 pub transport: TransportArg,
3374
3375 #[arg(long, value_enum, default_value_t = ProfileArg::Quick)]
3377 pub profile: ProfileArg,
3378
3379 #[arg(long, value_enum, default_value_t = OutputFormat::Text)]
3380 pub format: OutputFormat,
3382
3383 #[arg(long)]
3385 pub check: bool,
3386
3387 #[arg(long)]
3389 pub no_write: bool,
3390}
3391
3392#[derive(Debug, Subcommand)]
3393pub enum BenchCommand {
3395 Coverage {
3397 #[arg(long, value_enum, default_value_t = OutputFormat::Text)]
3398 format: OutputFormat,
3400 #[arg(long)]
3402 check: bool,
3403 },
3404 Baseline {
3406 #[command(subcommand)]
3407 command: BaselineCommand,
3409 },
3410}
3411
3412#[derive(Debug, Subcommand)]
3413pub enum BaselineCommand {
3415 Update {
3417 #[arg(long, value_enum, default_value_t = ProfileArg::Full)]
3419 profile: ProfileArg,
3420 #[arg(long)]
3422 allow_dirty: bool,
3423 },
3424}
3425
3426#[derive(Debug, Clone, Copy, PartialEq, Eq, ValueEnum, Default)]
3428pub enum TransportArg {
3429 #[default]
3431 All,
3432 Direct,
3434 Mcp,
3436 Http,
3438 System,
3440}
3441
3442#[derive(Debug, Clone, Copy, PartialEq, Eq, ValueEnum, Default)]
3444pub enum ProfileArg {
3445 #[default]
3447 Quick,
3448 Full,
3450 Ci,
3452}
3453
3454impl ProfileArg {
3455 pub fn name(self) -> &'static str {
3457 match self {
3458 ProfileArg::Quick => "quick",
3459 ProfileArg::Full => "full",
3460 ProfileArg::Ci => "ci",
3461 }
3462 }
3463}
3464
3465#[derive(Debug, Clone, Copy, PartialEq, Eq, ValueEnum, Default)]
3468pub enum OutputFormat {
3469 #[default]
3470 Text,
3472 Json,
3474}
3475
3476#[derive(Debug, Clone, Copy, PartialEq, Eq, ValueEnum, Default)]
3478pub enum DiscoveryMode {
3479 #[default]
3482 Vcs,
3483 Filesystem,
3485}
3486
3487#[derive(Debug, Clone, Copy, PartialEq, Eq, ValueEnum, Default)]
3490pub enum Transport {
3491 #[default]
3492 Stdio,
3494}
3495
3496#[derive(Debug, Args, Default, Clone)]
3498pub struct RepoArgs {
3499 #[arg(long, value_name = "PATH", global = true)]
3501 pub repo: Option<PathBuf>,
3502
3503 #[arg(long, value_enum, default_value_t = DiscoveryMode::Vcs, global = true)]
3505 pub discovery: DiscoveryMode,
3506
3507 #[arg(long, global = true)]
3509 pub strict: bool,
3510
3511 #[arg(long, value_name = "DIR", global = true)]
3514 pub share: Option<PathBuf>,
3515}
3516
3517#[derive(Debug, Args)]
3518pub struct PrsArgs {
3532 #[command(flatten)]
3533 pub repo: RepoArgs,
3535
3536 #[command(subcommand)]
3537 pub command: Option<PrsCommand>,
3539
3540 #[arg(long, value_enum, default_value_t = OutputFormat::Text, global = true)]
3541 pub format: OutputFormat,
3543}
3544
3545#[derive(Debug, Subcommand)]
3546pub enum PrsCommand {
3578 Status,
3580 Plan,
3582 Explain {
3584 number: u64,
3586 },
3587 Refresh,
3589 Drain {
3591 #[arg(long, default_value_t = 1)]
3593 max: usize,
3594 #[arg(long)]
3596 dry_run: bool,
3597 #[arg(long)]
3599 refresh: bool,
3600 #[arg(long, conflicts_with = "dry_run")]
3602 continuous: bool,
3603 #[arg(long, default_value_t = 300, value_parser = clap::value_parser!(u64).range(crate::integration::drain::INTERVAL_SECONDS))]
3605 interval: u64,
3606 #[arg(long, conflicts_with = "dry_run")]
3608 resume_after_failure: bool,
3609 },
3610 Cleanup {
3612 #[arg(long)]
3614 apply: bool,
3615 #[arg(long, conflicts_with = "apply")]
3617 dry_run: bool,
3618 },
3619 Repair {
3621 target: String,
3623 #[arg(long)]
3625 apply: bool,
3626 #[arg(long, conflicts_with = "apply")]
3628 dry_run: bool,
3629 },
3630 Events,
3632 Trains,
3634 Brief,
3636 ProveDryRun,
3638}
3639
3640#[derive(Debug, Args)]
3641pub struct OffloadArgs {
3662 #[command(flatten)]
3663 pub repo: RepoArgs,
3665
3666 #[arg(long, value_name = "FILE", global = true)]
3668 pub declaration: Option<PathBuf>,
3669
3670 #[command(subcommand)]
3671 pub command: OffloadCommand,
3673
3674 #[arg(long, value_enum, default_value_t = OutputFormat::Text, global = true)]
3675 pub format: OutputFormat,
3677}
3678
3679#[derive(Debug, Subcommand)]
3680pub enum OffloadCommand {
3700 Hosts,
3702 Probe,
3704 Derive {
3706 #[arg(default_value = ".")]
3708 worktree: PathBuf,
3709 #[arg(long, value_name = "HOST")]
3711 host: Option<String>,
3712 #[arg(long)]
3714 keep: bool,
3715 },
3716}
3717
3718#[derive(Debug, Args)]
3719pub struct WorktreeArgs {
3722 #[command(flatten)]
3723 pub repo: RepoArgs,
3725
3726 #[command(subcommand)]
3727 pub command: Option<WorktreeCommand>,
3729
3730 #[arg(long, value_enum, default_value_t = OutputFormat::Text, global = true)]
3731 pub format: OutputFormat,
3733}
3734
3735#[derive(Debug, Subcommand)]
3736pub enum WorktreeCommand {
3738 Status,
3740 List,
3742 Topology,
3744 Root,
3746 Path {
3748 branch: String,
3750 },
3751 Inspect {
3753 branch: String,
3755 },
3756 Create {
3758 #[arg(value_name = "BRANCH", required_unless_present = "issue")]
3760 branch: Option<String>,
3761
3762 #[arg(long, value_name = "REF")]
3764 base: Option<String>,
3765
3766 #[arg(long, value_name = "ID", conflicts_with = "branch")]
3768 issue: Option<String>,
3769 },
3770 Ensure {
3772 branch: String,
3774
3775 #[arg(long, value_name = "REF")]
3777 base: Option<String>,
3778 },
3779 Migrate {
3781 #[arg(long)]
3783 plan: bool,
3784
3785 #[arg(long)]
3787 dry_run: bool,
3788
3789 #[arg(long)]
3791 allow_copy: bool,
3792
3793 #[arg(long, value_name = "BRANCH")]
3795 only: Vec<String>,
3796
3797 #[arg(long)]
3799 include_ephemeral: bool,
3800 },
3801 Validate,
3803 Doctor,
3805 Guard {
3807 #[arg(long, short)]
3809 quiet: bool,
3810 },
3811 Repair {
3813 #[arg(long)]
3815 dry_run: bool,
3816 },
3817 Remove {
3819 selector: String,
3821
3822 #[arg(long)]
3824 force: bool,
3825 },
3826 Cleanup {
3828 #[arg(long)]
3832 remove: bool,
3833 },
3834 Uncommitted {
3836 #[arg(long, value_name = "DURATION")]
3838 older_than: Option<String>,
3839 },
3840 Branches {
3842 #[arg(long)]
3844 without_worktree: bool,
3845 },
3846}
3847
3848#[derive(Debug, Args)]
3849pub struct McpArgs {
3851 #[command(flatten)]
3852 pub repo: RepoArgs,
3854
3855 #[arg(long)]
3857 pub inspect: bool,
3858
3859 #[arg(long, value_enum, default_value_t = OutputFormat::Text)]
3861 pub format: OutputFormat,
3862
3863 #[arg(long, value_enum, default_value_t = Transport::Stdio)]
3865 pub transport: Transport,
3866
3867 #[arg(long)]
3870 pub standalone: bool,
3871
3872 #[arg(long, value_name = "HOST")]
3876 pub http_host: Option<String>,
3877
3878 #[arg(long, value_name = "PORT")]
3882 pub http_port: Option<u16>,
3883}
3884
3885pub const DEFAULT_PORT: u16 = 8741;
3888
3889const LINKED_PORT_BASE: u16 = DEFAULT_PORT + 1;
3892const LINKED_PORT_SPAN: u16 = 999;
3893
3894pub fn checkout_port(root: &std::path::Path) -> u16 {
3915 match crate::repository::git_identity(root) {
3916 Some(git) if git.linked => linked_port(&crate::repository::identity(root)),
3917 _ => DEFAULT_PORT,
3918 }
3919}
3920
3921pub fn linked_port(identity: &str) -> u16 {
3935 let lead = identity
3936 .get(..8)
3937 .and_then(|h| u32::from_str_radix(h, 16).ok())
3938 .unwrap_or(0);
3939 LINKED_PORT_BASE + u16::try_from(lead % u32::from(LINKED_PORT_SPAN)).unwrap_or(0)
3941}
3942
3943pub const LOOPBACK_HOST: &str = "127.0.0.1";
3945
3946pub const HTTP_HOST_ENV: &str = "MAJORDOMUS_HTTP_HOST";
3954
3955#[derive(Debug, Clone, Copy, PartialEq, Eq)]
3964pub enum HostOrigin {
3965 Flag,
3967 Environment,
3969 Default,
3971 LinkedWorktree,
3974}
3975
3976pub fn resolve_http_host(flag: Option<&str>, environment: Option<&str>) -> (String, HostOrigin) {
3999 if let Some(host) = flag {
4000 return (host.to_string(), HostOrigin::Flag);
4001 }
4002 match environment.map(str::trim).filter(|h| !h.is_empty()) {
4003 Some(host) => (host.to_string(), HostOrigin::Environment),
4004 None => (LOOPBACK_HOST.to_string(), HostOrigin::Default),
4005 }
4006}
4007
4008pub fn local_http_host(flag: Option<&str>) -> (String, HostOrigin) {
4021 let environment = std::env::var(HTTP_HOST_ENV).ok();
4022 let (host, origin) = resolve_http_host(flag, environment.as_deref());
4023 if origin == HostOrigin::Environment {
4024 tracing::info!(
4025 host = %host,
4026 "binding {host}: {HTTP_HOST_ENV} names it for this machine"
4027 );
4028 }
4029 (host, origin)
4030}
4031
4032pub fn checkout_http_host(flag: Option<&str>, root: &std::path::Path) -> (String, HostOrigin) {
4049 let environment = std::env::var(HTTP_HOST_ENV).ok();
4050 let linked = crate::repository::git_identity(root).is_some_and(|g| g.linked);
4051 let (host, origin) = resolve_checkout_http_host(flag, environment.as_deref(), linked);
4052 match origin {
4053 HostOrigin::Environment => tracing::info!(
4054 host = %host,
4055 "binding {host}: {HTTP_HOST_ENV} names it for this machine"
4056 ),
4057 HostOrigin::LinkedWorktree => tracing::info!(
4058 "binding {LOOPBACK_HOST}: {HTTP_HOST_ENV} names the machine's interface, and a \
4059 linked worktree leaves it to the primary checkout's server (--host binds one)"
4060 ),
4061 _ => {}
4062 }
4063 (host, origin)
4064}
4065
4066pub fn resolve_checkout_http_host(
4089 flag: Option<&str>,
4090 environment: Option<&str>,
4091 linked: bool,
4092) -> (String, HostOrigin) {
4093 match resolve_http_host(flag, environment) {
4094 (_, HostOrigin::Environment) if linked => {
4095 (LOOPBACK_HOST.to_string(), HostOrigin::LinkedWorktree)
4096 }
4097 resolved => resolved,
4098 }
4099}
4100
4101#[derive(Debug, Args)]
4102pub struct ServeArgs {
4104 #[command(flatten)]
4105 pub repo: RepoArgs,
4107
4108 #[command(subcommand)]
4109 pub command: Option<ServeCommand>,
4111
4112 #[arg(long, value_name = "HOST")]
4115 pub host: Option<String>,
4116
4117 #[arg(long)]
4120 pub port: Option<u16>,
4121
4122 #[arg(long)]
4124 pub fallback: bool,
4125
4126 #[arg(long, value_name = "SECONDS", default_value_t = 0)]
4128 pub idle: u64,
4129
4130 #[arg(long, value_name = "ID", conflicts_with_all = ["host", "port"])]
4134 pub deployment: Option<String>,
4135}
4136
4137pub const DEFAULT_IDLE_SECONDS: u64 = 900;
4143
4144#[derive(Debug, Subcommand)]
4145pub enum ServeCommand {
4180 Status {
4182 #[arg(long, value_enum, default_value_t = Checkouts::default())]
4185 checkouts: Checkouts,
4186 #[arg(long, value_enum, default_value_t = OutputFormat::Text)]
4188 format: OutputFormat,
4189 },
4190 Ensure {
4192 #[arg(long)]
4195 port: Option<u16>,
4196 #[arg(long, value_name = "SECONDS")]
4199 idle: Option<u64>,
4200 #[arg(long, value_name = "SECONDS", default_value_t = 20)]
4202 wait: u64,
4203 #[arg(long, value_enum, default_value_t = OutputFormat::Text)]
4205 format: OutputFormat,
4206 },
4207 Stop {
4209 #[arg(long, value_name = "SECONDS", default_value_t = 10)]
4211 wait: u64,
4212 },
4213}
4214
4215#[derive(Debug, Args)]
4216pub struct CapabilitiesArgs {
4218 #[command(flatten)]
4219 pub repo: RepoArgs,
4221
4222 #[command(subcommand)]
4223 pub command: CapabilitiesCommand,
4225}
4226
4227#[derive(Debug, Clone, Copy, PartialEq, Eq, ValueEnum, Default)]
4229pub enum SchemaSide {
4230 #[default]
4231 Input,
4233 Output,
4235}
4236
4237#[derive(Debug, Subcommand)]
4238pub enum CapabilitiesCommand {
4240 List {
4242 #[arg(long)]
4244 kind: Option<String>,
4245 #[arg(long)]
4247 exposure: Option<String>,
4248 #[arg(long, value_enum, default_value_t = OutputFormat::Text)]
4249 format: OutputFormat,
4251 },
4252 Describe {
4254 id: String,
4256 #[arg(long, value_enum, default_value_t = OutputFormat::Text)]
4257 format: OutputFormat,
4259 },
4260 Schema {
4262 id: String,
4264 #[arg(long, value_enum, default_value_t = SchemaSide::Input)]
4265 side: SchemaSide,
4267 },
4268 Projections {
4270 #[arg(long)]
4272 module: Option<String>,
4273 #[arg(long)]
4275 unmet: bool,
4276 #[arg(long, value_enum, default_value_t = OutputFormat::Text)]
4277 format: OutputFormat,
4279 },
4280 Validate,
4282}
4283
4284#[derive(Debug, Clone, Copy, PartialEq, Eq, ValueEnum, Default)]
4285pub enum GenerateTarget {
4287 #[default]
4288 All,
4290 Openapi,
4292 Docs,
4295 Benchmarks,
4297 Registry,
4299 Allow,
4301 Providers,
4303 Editors,
4306 Site,
4308 Manifest,
4310 Distribution,
4314 Web,
4316 Changelog,
4319 Deployment,
4321 Graph,
4323 Design,
4327 Economics,
4330}
4331
4332#[derive(Debug, Args)]
4333pub struct GenerateArgs {
4335 #[command(flatten)]
4336 pub repo: RepoArgs,
4338
4339 #[arg(value_enum, default_value_t = GenerateTarget::All)]
4341 pub target: GenerateTarget,
4342
4343 #[arg(long)]
4345 pub check: bool,
4346
4347 #[arg(long, value_name = "DIR")]
4349 pub out: Option<PathBuf>,
4350}
4351
4352#[derive(Debug, Args)]
4353pub struct CommandsArgs {
4355 #[command(flatten)]
4356 pub repo: RepoArgs,
4358
4359 #[command(subcommand)]
4360 pub command: Option<CommandsCommand>,
4362
4363 #[arg(long, value_enum, default_value_t = OutputFormat::Text, global = true)]
4364 pub format: OutputFormat,
4366}
4367
4368#[derive(Debug, Subcommand)]
4369pub enum CommandsCommand {
4371 List(CommandsListArgs),
4373 Show(CommandsShowArgs),
4375 Explain(CommandsShowArgs),
4377 Graph(CommandsGraphArgs),
4379 Bridge(CommandsBridgeArgs),
4381}
4382
4383#[derive(Debug, Args)]
4384pub struct CommandsListArgs {
4386 #[arg(long, value_enum)]
4388 pub origin: Option<CommandOrigin>,
4389
4390 #[arg(long, value_enum)]
4392 pub effect: Option<CommandEffect>,
4393
4394 #[arg(long, value_name = "TEXT")]
4396 pub search: Option<String>,
4397}
4398
4399#[derive(Debug, Args)]
4400pub struct CommandsShowArgs {
4402 pub id: String,
4404}
4405
4406#[derive(Debug, Args)]
4407pub struct CommandsGraphArgs {
4409 #[arg(long)]
4411 pub check: bool,
4412}
4413
4414#[derive(Debug, Args)]
4415pub struct CommandsBridgeArgs {
4417 #[arg(long)]
4419 pub check: bool,
4420}
4421
4422#[derive(Debug, Clone, Copy, PartialEq, Eq, ValueEnum)]
4424pub enum CommandOrigin {
4425 Executable,
4427 Tool,
4429 Workflow,
4431}
4432
4433#[derive(Debug, Clone, Copy, PartialEq, Eq, ValueEnum)]
4435pub enum CommandEffect {
4436 ReadOnly,
4438 LocalMutation,
4440 RepositoryMutation,
4442 NetworkMutation,
4444 Destructive,
4446}
4447
4448#[derive(Debug, Args)]
4449pub struct CompletionArgs {
4451 #[command(flatten)]
4452 pub repo: RepoArgs,
4454
4455 #[command(subcommand)]
4456 pub command: Option<CompletionCommand>,
4458}
4459
4460#[derive(Debug, Subcommand)]
4461pub enum CompletionCommand {
4463 Query(CompletionQueryArgs),
4465 Init(CompletionInitArgs),
4467 Install(CompletionInstallArgs),
4469}
4470
4471#[derive(Debug, Args)]
4472pub struct CompletionQueryArgs {
4474 #[arg(long, value_enum, default_value_t = CompletionSurface::Cli)]
4476 pub surface: CompletionSurface,
4477
4478 #[arg(long, value_name = "N")]
4480 pub cursor: Option<usize>,
4481
4482 #[arg(long, value_enum, default_value_t = OutputFormat::Text)]
4484 pub format: OutputFormat,
4485
4486 #[arg(trailing_var_arg = true, value_name = "WORD")]
4488 pub words: Vec<String>,
4489}
4490
4491#[derive(Debug, Args)]
4492pub struct CompletionInitArgs {
4494 #[arg(long, value_enum, default_value_t = CompletionShell::Zsh)]
4496 pub shell: CompletionShell,
4497}
4498
4499#[derive(Debug, clap::Args)]
4501pub struct CompletionInstallArgs {
4502 #[arg(long, value_enum, default_value_t = CompletionShell::Zsh)]
4504 pub shell: CompletionShell,
4505 #[arg(long, value_name = "PATH")]
4507 pub rc: Option<std::path::PathBuf>,
4508 #[arg(long)]
4510 pub remove: bool,
4511 #[arg(long)]
4513 pub dry_run: bool,
4514}
4515
4516#[derive(Debug, Clone, Copy, PartialEq, Eq, ValueEnum)]
4518pub enum CompletionSurface {
4519 Cli,
4521 Workflow,
4523}
4524
4525#[derive(Debug, Clone, Copy, PartialEq, Eq, ValueEnum)]
4527pub enum CompletionShell {
4528 Zsh,
4530 Bash,
4532 Fish,
4534}
4535
4536#[derive(Debug, Args)]
4537pub struct DevcontextArgs {
4567 #[command(flatten)]
4568 pub repo: RepoArgs,
4570
4571 #[command(subcommand)]
4572 pub command: DevcontextCommand,
4574
4575 #[arg(long, value_enum, default_value_t = OutputFormat::Text, global = true)]
4576 pub format: OutputFormat,
4578}
4579
4580#[derive(Debug, Subcommand)]
4581pub enum DevcontextCommand {
4619 Compile(DevcontextRequest),
4621 Explain {
4623 uri: String,
4625 #[command(flatten)]
4626 request: DevcontextRequest,
4628 },
4629 Policy,
4631}
4632
4633#[derive(Debug, Clone, Args)]
4634pub struct DevcontextRequest {
4685 #[arg(long)]
4687 pub issue: Option<String>,
4688 #[arg(long)]
4690 pub milestone: Option<String>,
4691 #[arg(long)]
4693 pub intent: Option<String>,
4694 #[arg(long = "path")]
4696 pub paths: Vec<String>,
4697 #[arg(long = "uri")]
4699 pub uris: Vec<String>,
4700 #[arg(long)]
4702 pub budget_tokens: Option<u64>,
4703 #[arg(long)]
4705 pub max_depth: Option<usize>,
4706 #[arg(long)]
4708 pub floor: Option<f64>,
4709 #[arg(long)]
4711 pub all_blocking_rules: bool,
4712}
4713
4714pub mod docs;
4725pub mod local;
4726mod validate;
4727
4728pub use docs::tree;
4729pub use docs::{
4730 document, render, route, ArgDoc, CliDocument, CommandDoc, ExampleView, PossibleValueDoc,
4731 SetupView, DECLARATION, ROUTE_PREFIX, SCHEMA,
4732};
4733pub use validate::{parse, validate, Violation};
4734
4735#[derive(Debug, Clone, Copy, PartialEq, Eq)]
4739pub enum Expect {
4740 Success,
4742 ExitCode(u8),
4744 StdoutContains(&'static [&'static str]),
4746 Json(&'static [&'static str]),
4749 HttpReady(&'static str),
4752 McpReady,
4755}
4756
4757impl Expect {
4758 pub fn describe(self) -> String {
4760 match self {
4761 Expect::Success => "exits 0".to_string(),
4762 Expect::ExitCode(c) => format!("exits {c}"),
4763 Expect::StdoutContains(f) => format!("exits 0; prints {}", f.join(", ")),
4764 Expect::Json(p) => format!(
4765 "exits 0; prints one JSON document carrying {}",
4766 p.join(", ")
4767 ),
4768 Expect::HttpReady(path) => {
4769 format!("binds a port, answers GET {path}, exits 0 when stopped")
4770 }
4771 Expect::McpReady => {
4772 "answers initialize and tools/list on stdio, and exits 0 at end of input"
4773 .to_string()
4774 }
4775 }
4776 }
4777}
4778
4779#[derive(Debug, Clone, Copy, PartialEq, Eq)]
4784pub struct ExampleDoc {
4785 pub id: &'static str,
4787 pub title: &'static str,
4789 pub description: &'static str,
4791 pub argv: &'static [&'static str],
4793 pub setup: &'static [&'static [&'static str]],
4795 pub expect: Expect,
4797}
4798
4799#[derive(Debug, Clone, Copy, PartialEq, Eq)]
4804pub struct CommandExamples {
4805 pub command: &'static str,
4807 pub examples: &'static [ExampleDoc],
4809}
4810
4811pub const EXAMPLES: &[CommandExamples] = &[
4819 CommandExamples {
4820 command: "commit",
4821 examples: &[ExampleDoc {
4822 id: "commit-default-plan",
4823 title: "What this tree would commit, and why",
4824 description: "`commit` with nothing after it plans, because that is what a person wants when they ask about committing. The branch, its upstream and divergence, what is staged and what is not, and the commits the history's own scoping supports — each with the evidence for it rather than an assertion. A clean tree says so.",
4825 argv: &["commit"],
4826 setup: &[],
4827 expect: Expect::StdoutContains(&["branch", "tree", "fingerprint"]),
4828 }],
4829 },
4830 CommandExamples {
4831 command: "commit plan",
4832 examples: &[
4833 ExampleDoc {
4834 id: "commit-plan",
4835 title: "The plan, with the fingerprint that makes it refusable",
4836 description: "The fingerprint is the repository, the worktree, HEAD and a hash over every change with its stage. A caller holding a plan compares it with the tree in front of it and is told what moved — `HEAD moved from a1b2c3d4e to e4f5a6b70` — rather than being told nothing and committing somebody else's staged work.",
4837 argv: &["commit", "plan"],
4838 setup: &[],
4839 expect: Expect::StdoutContains(&["fingerprint", "nothing staged"]),
4840 },
4841 ExampleDoc {
4842 id: "commit-plan-json",
4843 title: "The same answer, as the shape the API and MCP return",
4844 description: "One domain model behind every projection: this document is what `GET /api/v1/commit/plan` returns and what the `majordomus_commit_plan` tool answers, with the working tree, every group with its rationale, and the fingerprint.",
4845 argv: &["commit", "plan", "--format", "json"],
4846 setup: &[],
4847 expect: Expect::Json(&["/fingerprint/repository", "/fingerprint/worktree", "/tree/changes"]),
4848 },
4849 ],
4850 },
4851 CommandExamples {
4852 command: "commit scopes",
4853 examples: &[ExampleDoc {
4854 id: "commit-scopes",
4855 title: "The scope vocabulary, learned rather than declared",
4856 description: "Every scope this repository's own commits use, how often, and the directories each one is written about — read from at most 1500 commits of the log. Nothing here is configured: a subsystem committed today is in the vocabulary today, and one nobody has touched sinks on its own. A repository whose history is not conventional yields an empty vocabulary and says how many commits it read.",
4857 argv: &["commit", "scopes"],
4858 setup: &[],
4859 expect: Expect::StdoutContains(&["learned from"]),
4860 }],
4861 },
4862 CommandExamples {
4863 command: "commit validate",
4864 examples: &[ExampleDoc {
4865 id: "commit-validate-rev",
4866 title: "The verdict on a commit that is already made",
4867 description: "`--rev` judges the message of any revision `git show` accepts; without it the message is read from a file or from standard input, which is the shape the `commit-msg` hook has. The exit code is the verdict: 0 when nothing of error severity was found, 10 when something was. Here the repository's first commit is subject `install`, which is not `type(scope): subject`, so the answer is 10 and the finding names the eleven type words.",
4868 argv: &["commit", "validate", "--rev", "HEAD"],
4869 setup: &[],
4870 expect: Expect::ExitCode(10),
4871 }],
4872 },
4873 CommandExamples {
4874 command: "commit history",
4875 examples: &[ExampleDoc {
4876 id: "commit-history",
4877 title: "A whole range judged in one pass",
4878 description: "One process for the range rather than one per commit: this reads 1755 commits of this repository's own history in about three and a half seconds, which is what lets `scripts/ci/commit-policy` be a gate rather than a nightly job. It reports how many were read, how many git composed and are therefore exempt, and how many carry an error — and exits 10 when any does.",
4879 argv: &["commit", "history"],
4880 setup: &[],
4881 expect: Expect::ExitCode(10),
4882 }],
4883 },
4884 CommandExamples {
4885 command: "product",
4886 examples: &[ExampleDoc {
4887 id: "product-default-list",
4888 title: "What the product does, as the layer declares it",
4889 description: "`product` with nothing after it lists the features, because listing is what a person wants when they ask what the tool is for. Every column is derived: the surfaces a feature is exposed through come from the modules, commands and kinds it names, never from the file.",
4890 argv: &["product"],
4891 setup: &[],
4892 expect: Expect::StdoutContains(&["SLUG", "SURFACES", "feature(s)"]),
4893 }],
4894 },
4895 CommandExamples {
4896 command: "product list",
4897 examples: &[
4898 ExampleDoc {
4899 id: "product-list",
4900 title: "Every stable feature, in presentation order",
4901 description: "Drafts are excluded unless `--all` is given; `--featured` narrows to the features the homepage shows. The filters are the facets the model derives — an area, a module, a command, a surface — so a module added to the executable is a filter without anything being registered.",
4902 argv: &["product", "list"],
4903 setup: &[],
4904 expect: Expect::StdoutContains(&["SLUG", "fixture-feature"]),
4905 },
4906 ExampleDoc {
4907 id: "product-list-json",
4908 title: "The same, as the shape the API and MCP answer with",
4909 description: "One domain model behind every projection: this document is what `GET /api/v1/product/features` returns and what the `majordomus_features` tool answers, with the counts, the fingerprint and the surfaces of every feature.",
4910 argv: &["product", "list", "--format", "json"],
4911 setup: &[],
4912 expect: Expect::Json(&["/counts/features", "/features/0/surfaces", "/fingerprint"]),
4913 },
4914 ],
4915 },
4916 CommandExamples {
4917 command: "product show",
4918 examples: &[ExampleDoc {
4919 id: "product-show",
4920 title: "One feature, with everything derived from what it names",
4921 description: "The record as its file declares it, then what nobody authored: the capabilities of its modules with their tools and routes, the commands with their summaries, the objects of its kinds counted, the rules with their class, the documents, the decisions, the claims with their status, the moments it answers, and the interfaces all of that adds up to.",
4922 argv: &["product", "show", "fixture-feature"],
4923 setup: &[],
4924 expect: Expect::StdoutContains(&["fixture-feature", "surfaces", "derived"]),
4925 }],
4926 },
4927 CommandExamples {
4928 command: "product domains",
4929 examples: &[ExampleDoc {
4930 id: "product-domains",
4931 title: "The few things the product controls, and the features under each",
4932 description: "One block per domain in presentation order: its promise, the failure it answers, and the stable features that name it, with the interfaces, claims and use cases they add up to. A domain lists nothing itself; every member and count is derived from the features.",
4933 argv: &["product", "domains"],
4934 setup: &[],
4935 expect: Expect::StdoutContains(&["domain(s)"]),
4936 }],
4937 },
4938 CommandExamples {
4939 command: "product matrix",
4940 examples: &[ExampleDoc {
4941 id: "product-matrix",
4942 title: "Every feature against every interface, and what no feature names",
4943 description: "One row per feature with a mark per surface, then every module of the executable, every public command and every kind of the layer with the features that name it. A row with no feature is a gap the product page cannot hide.",
4944 argv: &["product", "matrix"],
4945 setup: &[],
4946 expect: Expect::StdoutContains(&["FEATURE", "cli", "MODULE"]),
4947 }],
4948 },
4949 CommandExamples {
4950 command: "product providers",
4951 examples: &[ExampleDoc {
4952 id: "product-providers",
4953 title: "Every provider the tool has an adapter for",
4954 description: "One line per template the distribution ships, with the bootstraps this repository's policy renders through it, the client configuration it carries for the shared MCP server, and the hooks the policy wires. The set is the templates; nothing here is a list of vendors.",
4955 argv: &["product", "providers"],
4956 setup: &[],
4957 expect: Expect::StdoutContains(&["PROVIDER", "agents"]),
4958 }],
4959 },
4960 CommandExamples {
4961 command: "product validate",
4962 examples: &[ExampleDoc {
4963 id: "product-validate",
4964 title: "Check the model before anything projects it",
4965 description: "A reference that resolves to nothing, with the nearest candidate; a duplicate identity; a file name that disagrees with its id; a draft that is featured; a stable feature under its floors; and every module, command or kind no feature names. Exit 10 on any error.",
4966 argv: &["product", "validate"],
4967 setup: &[],
4968 expect: Expect::StdoutContains(&["feature(s)", "valid"]),
4969 }],
4970 },
4971 CommandExamples {
4972 command: "release",
4973 examples: &[ExampleDoc {
4974 id: "release-changelog",
4975 title: "What has shipped, and what has not",
4976 description: "`release` with nothing after it renders the changelog. Every line of it is derived — a section per release the layer records, its decisions the ADRs dated inside that release's window, its changes the conventional commits in its range — so there is no file anyone can forget to update.",
4977 argv: &["release"],
4978 setup: &[],
4979 expect: Expect::StdoutContains(&["Changelog"]),
4980 }],
4981 },
4982 CommandExamples {
4983 command: "release changelog",
4984 examples: &[ExampleDoc {
4985 id: "release-changelog-json",
4986 title: "The same document every other surface answers with",
4987 description: "What `GET /api/v1/changelog` returns, what the MCP resource `majordomus://changelog` carries, and what `majordomus generate changelog` writes into the reference. One value, four renderings.",
4988 argv: &["release", "changelog", "--format", "json"],
4989 setup: &[],
4990 expect: Expect::Json(&["/schema", "/current", "/sections"]),
4991 }],
4992 },
4993 CommandExamples {
4994 command: "release version",
4995 examples: &[ExampleDoc {
4996 id: "release-version",
4997 title: "The version, and the one the contract requires next",
4998 description: "The version is authored in one place, the crate manifest, and the shell tool reads its projection, share/version.txt, because an installed tree has no Cargo.toml. This says what the manifest declares, whether the projection states it, and — exit 10 — any version written down by hand where the tool's own files live. `next` is the public contract's answer, the version `release analyze` requires (the declared version when it already satisfies the contract, otherwise the smallest one it allows); `decided_by` names who answered, and the bump the commit subjects imply is carried as evidence. This fixture has published no release with a registry, so the contract cannot be measured: `next` is absent and `decided_by` is `undecided`, with the reason in `contract_unreadable` — an unmeasurable baseline is refused, not guessed.",
4999 argv: &["release", "version", "--format", "json"],
5000 setup: &[],
5001 expect: Expect::Json(&["/declared", "/agree", "/bump", "/decided_by"]),
5002 }],
5003 },
5004 CommandExamples {
5005 command: "release analyze",
5006 examples: &[ExampleDoc {
5007 id: "release-analyze",
5008 title: "What the contract did, and the smallest version it allows",
5009 description: "The public capability surface of this tree against the one the last release published, and the smallest version this tree may therefore declare. The compatibility level is measured from the contract rather than read off the commit subjects: a capability, route, MCP tool, command or required field a caller could hold and cannot any more is breaking whatever the commit that removed it called itself. The same value answers `GET /api/v1/release/analysis`, the `majordomus_release_analysis` MCP tool, the Cockpit's Release page and the `version-surface` gate. A repository that has published nothing has no baseline to measure against, and says so with exit 12 rather than reporting an empty diff — which would read as \"nothing changed\".",
5010 argv: &["release", "analyze", "--format", "json"],
5011 setup: &[],
5012 expect: Expect::ExitCode(12),
5013 }],
5014 },
5015 CommandExamples {
5016 command: "release next",
5017 examples: &[ExampleDoc {
5018 id: "release-next",
5019 title: "What a landing would raise the version to",
5020 description: "The version the integration executor allocates when it lands a head on the trunk (ADR 0134): the trunk's version, the head's movement of the public contract measured against the trunk's committed registry, the policy floor and any exemption, and the larger of the requirement and the floor — read from git at the two refs, never from the branch's own version. This fixture has no trunk to raise from, and says so with exit 12 rather than inventing a number.",
5021 argv: &["release", "next", "--format", "json"],
5022 setup: &[],
5023 expect: Expect::ExitCode(12),
5024 }],
5025 },
5026 CommandExamples {
5027 command: "release bump",
5028 examples: &[ExampleDoc {
5029 id: "release-bump-dry-run",
5030 title: "Raising it, in the one place it is authored",
5031 description: "The one writer, and it computes nothing: it reads the plan `release analyze` prints and applies it, so the version it writes is the measured minimum rather than a judgement of its own. `--level` and `--exact` name a higher version when a person means more than the contract did, and are refused below the minimum with nothing written — an override that could undershoot would make the measurement decorative. It rewrites the manifest's one version line and the lock's record of it, reads both back, and leaves share/version.txt and the generator stamps to scripts/derive. A repository that has published nothing has no baseline to raise from — the example runs in one — and says so with exit 12 rather than inventing a number.",
5032 argv: &["release", "bump", "--dry-run"],
5033 setup: &[],
5034 expect: Expect::ExitCode(12),
5035 }],
5036 },
5037 CommandExamples {
5038 command: "completion install",
5039 examples: &[ExampleDoc {
5040 id: "completion-install-dry-run",
5041 title: "The one line a person adds to their shell, added for them",
5042 description: "Writes the integration into the shell's startup file between `# >>> MAJORDOMUS >>>` markers: nothing outside them is touched, running it twice changes nothing, and `--remove` takes it out again. It is never a side effect of anything else — installing into a person's home directory is its own decision, so it is its own command. `--dry-run` says what would change and writes nothing.",
5043 argv: &["completion", "install", "--shell", "zsh", "--dry-run"],
5044 setup: &[],
5045 expect: Expect::Success,
5046 }],
5047 },
5048 CommandExamples {
5049 command: "env",
5050 examples: &[ExampleDoc {
5051 id: "env-status",
5052 title: "What this checkout is",
5053 description: "`env` with nothing after it resolves the whole snapshot: the project and its version, the repository and its layer, version control, the toolchains the repository declares, what the layer holds counted per kind, the workflows the runner describes, the provider projections against the policy that renders them, and the local services. This is the resolution that counts the layer, so it builds the index and writes the cache the banner reads.",
5054 argv: &["env"],
5055 setup: &[],
5056 expect: Expect::StdoutContains(&["project", "repository", "resolution"]),
5057 }],
5058 },
5059 CommandExamples {
5060 command: "env status",
5061 examples: &[ExampleDoc {
5062 id: "env-status-json",
5063 title: "The snapshot as one document",
5064 description: "The same value the HTTP route `/api/v1/environment` and the MCP resource `majordomus://environment` answer with, and the value the banner renders. Every field carries where it came from under `provenance`, and a value nothing could resolve is absent rather than zero.",
5065 argv: &["env", "status", "--format", "json"],
5066 setup: &[],
5067 expect: Expect::Json(&["/schema", "/project/version", "/repository/name", "/provenance"]),
5068 }],
5069 },
5070 CommandExamples {
5071 command: "env banner",
5072 examples: &[ExampleDoc {
5073 id: "env-banner-compact",
5074 title: "The two-line form, at a width you choose",
5075 description: "What `direnv` renders on entering the repository. It resolves fast — it never builds the index — and it writes to standard error, because direnv reads the standard output of a `.envrc` as the environment it is applying. `--width` renders as if the terminal were that wide, which is what makes the layout testable.",
5076 argv: &["env", "banner", "--mode", "compact", "--width", "80"],
5077 setup: &[],
5078 expect: Expect::Success,
5079 }],
5080 },
5081 CommandExamples {
5082 command: "env export",
5083 examples: &[ExampleDoc {
5084 id: "env-export-direnv",
5085 title: "The assignments a shell in this repository wants",
5086 description: "Assignments and nothing else, safe to `eval`: no command runs, no file is touched, and every value is quoted so that a repository path holding a quote or a `$(...)` cannot become shell code. This is the whole of what `.envrc` needs from Majordomus.",
5087 argv: &["env", "export", "--shell", "direnv"],
5088 setup: &[],
5089 expect: Expect::StdoutContains(&["export MAJORDOMUS_ROOT="]),
5090 }],
5091 },
5092 CommandExamples {
5093 command: "env enter",
5094 examples: &[ExampleDoc {
5095 id: "env-enter",
5096 title: "Everything entering this repository is, as one call",
5097 description: "What the file a shell evaluates on entry runs, and the only call it makes (ADR 0043): the assignments on standard output for `eval`, the banner on standard error, the workflow bridge refreshed when a declaration behind it moved, and the repository's shared server ensured when nothing is serving this checkout. It never builds, never ensures from an executable older than its sources, never waits for a server it started to answer, and never exits non-zero — a non-zero exit here would make direnv report that the whole environment failed. `--no-runtime` is what this example passes, because an example is not the place to start a server.",
5098 argv: &["env", "enter", "--shell", "direnv", "--no-banner", "--no-bridge", "--no-runtime"],
5099 setup: &[],
5100 expect: Expect::StdoutContains(&["export MAJORDOMUS_ROOT="]),
5101 }],
5102 },
5103 CommandExamples {
5104 command: "env explain",
5105 examples: &[ExampleDoc {
5106 id: "env-explain-field",
5107 title: "Where one value came from",
5108 description: "An inferred system without provenance is magic. Every field of the snapshot can name the file, command or compile-time constant that decided it, the resolver that read it, and whether it was read now, taken from the cache, or not resolved at all.",
5109 argv: &["env", "explain", "project.version"],
5110 setup: &[],
5111 expect: Expect::StdoutContains(&["project.version", "source", "resolver"]),
5112 }],
5113 },
5114 CommandExamples {
5115 command: "env preflight",
5116 examples: &[ExampleDoc {
5117 id: "env-preflight-json",
5118 title: "What is in force here, and what proves it",
5119 description: "One verdict per claim — `verified`, `active`, `fresh`, `stale`, `degraded`, `unavailable`, `failed`, `unknown` or `not_applicable` — and the evidence it rests on: the file, command or loopback answer that was read. A rule file on disk is not a rule anything enforces, an address that accepts a connection is not a server of this version, and a recorded test run at another commit does not verify this tree, so none of them is reported as one. `attention` lists what needs a look, most urgent first.",
5120 argv: &["env", "preflight", "--format", "json"],
5121 setup: &[],
5122 expect: Expect::Json(&["/schema", "/sections/0/checks/0/verdict", "/attention"]),
5123 }],
5124 },
5125 CommandExamples {
5126 command: "run",
5127 examples: &[ExampleDoc {
5128 id: "run-demonstrate",
5129 title: "Watch an execution happen",
5130 description: "`run` starts a capability as an execution and follows it to its end: every step, every line it logs and every advance of its progress, as the handler reports them. `executions.demonstrate` exists to make that visible without waiting for real work — it reads nothing and writes nothing, and its only effect is the events it produces. The same execution, started from the Cockpit, streams the same events to a browser.",
5131 argv: &["run", "executions.demonstrate", "--input", "{\"steps\":2,\"delay_ms\":0}", "--format", "json"],
5132 setup: &[],
5133 expect: Expect::Json(&["/state", "/id", "/output/steps", "/steps/0/name"]),
5134 }],
5135 },
5136 CommandExamples {
5137 command: "executions",
5138 examples: &[ExampleDoc {
5139 id: "executions-default-list",
5140 title: "What has run",
5141 description: "`executions` with nothing after it lists what the server serving this repository has run, newest first. In a checkout where no server is running it says so rather than pretending: an execution lives in the process that accepted it.",
5142 argv: &["executions"],
5143 setup: &[],
5144 expect: Expect::StdoutContains(&["execution"]),
5145 }],
5146 },
5147 CommandExamples {
5148 command: "evidence show",
5149 examples: &[
5150 ExampleDoc {
5151 id: "evidence-show-json",
5152 title: "The whole join, as one document",
5153 description: "The same answer `GET /api/v1/evidence` and the MCP tool `majordomus_evidence` return: every claim with its proof state, the sentence that explains how that state was derived, the execution behind it, the files that have changed since, and the command that produces the proof again. The tallies count the whole matrix even when the claims are filtered, so a narrowed answer never misreports how much of it was examined.",
5154 argv: &["evidence", "show", "--format", "json"],
5155 setup: &[],
5156 expect: Expect::Json(&["/claims", "/totals", "/ledger/path", "/findings"]),
5157 },
5158 ExampleDoc {
5159 id: "evidence-show-presented",
5160 title: "The checked-out commit, judged as committed",
5161 description: "The reading a site built from this commit needs: every claim judged from the ledger the commit holds rather than the working tree's, against the commit's own tree, measured without the ledger's working copy. The first line names what was judged. A run the working ledger holds that the commit's does not can only withhold `proven`, and is named when there is one; a revision other than the checked-out commit is refused.",
5162 argv: &["evidence", "show", "--presented", "HEAD"],
5163 setup: &[],
5164 expect: Expect::StdoutContains(&["judged at", "as committed"]),
5165 },
5166 ],
5167 },
5168 CommandExamples {
5169 command: "evidence claim",
5170 examples: &[ExampleDoc {
5171 id: "evidence-claim-absent",
5172 title: "A claim the matrix does not declare",
5173 description: "A claim id nothing declares is a not-found rather than an empty answer. A typo that read as `this claim has no evidence` is the one answer this command must never give, because it is indistinguishable from the finding the whole subsystem exists to report.",
5174 argv: &["evidence", "claim", "no-such-claim-exists"],
5175 setup: &[],
5176 expect: Expect::ExitCode(13),
5177 }],
5178 },
5179 CommandExamples {
5180 command: "evidence proves",
5181 examples: &[ExampleDoc {
5182 id: "evidence-proves-unknown",
5183 title: "Something that names no test",
5184 description: "A test is named by its identity (`suite:<case>`, `crate:<binary>`) or by the path a claim writes down, and the two resolve to the same thing. An argument that is neither is refused with the spellings it could have been, rather than answered with a test that proves nothing.",
5185 argv: &["evidence", "proves", "not-a-test"],
5186 setup: &[],
5187 expect: Expect::ExitCode(13),
5188 }],
5189 },
5190 CommandExamples {
5191 command: "delivery report",
5192 examples: &[ExampleDoc {
5193 id: "delivery-report-json",
5194 title: "Does each feature exist, dimension by dimension",
5195 description: "The same answer `GET /api/v1/delivery` and the MCP tool `majordomus_delivery` return: every feature ordered by id, each of the six dimensions with its verdict, reason and remediation, the development stage of a feature that does not exist, the paths it is implemented by, and the publication read once for all of them. A repository with no site and no trunk says unknown, and unknown is never a pass, so nothing here exists.",
5196 argv: &["delivery", "report", "--format", "json"],
5197 setup: &[],
5198 expect: Expect::Json(&["/features/0/dimensions", "/tallies/exists", "/publication/identity/state"]),
5199 }],
5200 },
5201 CommandExamples {
5202 command: "delivery show",
5203 examples: &[ExampleDoc {
5204 id: "delivery-show",
5205 title: "One feature, and what stands between it and existing",
5206 description: "Every dimension of one feature with the sentence that decided it and what would change it. `--check` turns the conjunction into the exit code: 10 unless every dimension passes. An id the layer does not declare is not found, never reported as not delivered.",
5207 argv: &["delivery", "show", "fixture-feature"],
5208 setup: &[],
5209 expect: Expect::StdoutContains(&["fixture-feature", "on_master", "NOT DELIVERED"]),
5210 }],
5211 },
5212 CommandExamples {
5213 command: "entity kinds",
5214 examples: &[ExampleDoc {
5215 id: "entity-kinds-json",
5216 title: "Every kind of the layer, and whether every object of it has an address",
5217 description: "The catalogue the Cockpit's navigation and the site's indexes are both derived from. Nothing enumerates kinds: each one is here because the index holds an object of it, and each carries the route of its own listing. `collisions` is the one way an object can fail to be addressable — two identities of one kind that reduce to one route — and the healthy answer is none.",
5218 argv: &["entity", "kinds", "--format", "json"],
5219 setup: &[],
5220 expect: Expect::Json(&["/kinds", "/count", "/routable"]),
5221 }],
5222 },
5223 CommandExamples {
5224 command: "entity show",
5225 examples: &[
5226 ExampleDoc {
5227 id: "entity-show-rule",
5228 title: "One entity at its own address",
5229 description: "The same answer `GET /api/v1/entity` and the MCP tool `majordomus_entity` return, and the same one the Cockpit lays out: the entity's route, the references it declares, the references that resolve to it — derived, never declared — the surfaces that answer for it, what can be said about the executable artefacts it names, and its public documentation page (`documentation`, null here because this fixture has no site/data/publication.toml). The address is the route's two segments, which is the shorter spelling of the URI and the one the Cockpit's address bar holds.",
5230 argv: &["entity", "show", "rule/project-alpha-1", "--format", "json"],
5231 setup: &[],
5232 expect: Expect::Json(&[
5233 "/uri",
5234 "/route",
5235 "/relations",
5236 "/surfaces",
5237 "/evidence/state",
5238 ]),
5239 },
5240 ExampleDoc {
5241 id: "entity-show-absent",
5242 title: "An address the layer does not serve",
5243 description: "An entity nothing declares is a not-found rather than an empty answer, for the reason `rules show` gives: a typo that read as `this entity is joined to nothing` is indistinguishable from the finding the page exists to show.",
5244 argv: &["entity", "show", "rule/no-such-rule"],
5245 setup: &[],
5246 expect: Expect::ExitCode(12),
5247 },
5248 ],
5249 },
5250 CommandExamples {
5251 command: "rules report",
5252 examples: &[ExampleDoc {
5253 id: "rules-report-json",
5254 title: "Every rule against the proof there is for it",
5255 description: "The same answer `GET /api/v1/rules` and the MCP tool `majordomus_rules` return: per rule, its class, the mode it declares, the validator and the cases it names, whether each is in the tree, the execution behind each, the gates that run them, and the sentence explaining how the state was derived. The tallies count the whole corpus even when the rules are filtered, and `review_only` is counted apart from `passing` so that a rule a person enforces is never added to a total that reads as proof.",
5256 argv: &["rules", "report", "--format", "json"],
5257 setup: &[],
5258 expect: Expect::Json(&["/rules", "/states", "/coverage/rules", "/findings"]),
5259 }],
5260 },
5261 CommandExamples {
5262 command: "brief",
5263 examples: &[ExampleDoc {
5264 id: "brief-line",
5265 title: "The one-line brief, composed here when no server answers",
5266 description: "The same answer `GET /api/v1/brief` and the MCP tool `majordomus_brief` return, rendered as its one line: this session's task or episode and branch, the peers of the boards read, the mesh, the integration queue and the derive lock, every section present whatever its state. The command line asks the server holding this checkout's lease, which holds the board and the mesh; this fixture has no server, so the brief is composed by this process and says so in its multi-line form.",
5267 argv: &["brief", "--line", "--this-checkout"],
5268 setup: &[],
5269 expect: Expect::Success,
5270 }],
5271 },
5272 CommandExamples {
5273 command: "dashboard overview",
5274 examples: &[ExampleDoc {
5275 id: "dashboard-overview-json",
5276 title: "The four questions, every card with the answer it was read from",
5277 description: "The same answer `GET /api/v1/dashboard/overview`, the MCP tool `majordomus_dashboard_overview` and the first section of the Cockpit's overview return: is it healthy, what changed, what is broken, what needs action, each answered by cards read out of `health.report`, `release.version`, `plan.status`, `worktree.status`, `plan.next`, `continuity.state` and `peers.list`. Every card carries its source capability, the input it was asked with and the JSON pointer its value was read from, so `majordomus run <capability>` read at that pointer gives the same value. The exit code is the overview's own word: 0 for ok and warn, 10 for fail and unknown. This fixture commits no registry manifest, so `health.report` cannot decide one of its checks, the health card is `unknown` rather than ok, and the answer is 10.",
5278 argv: &["dashboard", "overview", "--format", "json"],
5279 setup: &[],
5280 expect: Expect::ExitCode(10),
5281 }],
5282 },
5283 CommandExamples {
5284 command: "pack plan",
5285 examples: &[ExampleDoc {
5286 id: "pack-plan-chatgpt-json",
5287 title: "What the ChatGPT profile would pack, before anything is written",
5288 description: "The same answer `GET /api/v1/pack/plan?profile=chatgpt` and the MCP tool `majordomus_pack_plan` return: the files carried with their bytes and o200k_base tokens, every file left out by reason under `/dropped` and `/dropped_files`, the shards under `/shards`, and every finding that would refuse the build under `/findings`. The exit code is the verdict: 0 when the pack can be built, 10 on a finding, 12 when the tree cannot be read.",
5289 argv: &["pack", "plan", "chatgpt", "--format", "json"],
5290 setup: &[],
5291 expect: Expect::Json(&["/dropped", "/shards", "/findings", "/passes"]),
5292 }],
5293 },
5294 CommandExamples {
5295 command: "pack build",
5296 examples: &[ExampleDoc {
5297 id: "pack-build-chatgpt",
5298 title: "Write the ChatGPT pack and read it back",
5299 description: "Plans with the profile, writes `00-INDEX.md`, the shards and `pack.json` under `tmp/packs/` only when the plan passes, then verifies what it wrote: every digest, no stray file, no binary, artifact, link or worktree, every file within the token budget. It prints the plan and the verdict; the files to upload are the index and the shards.",
5300 argv: &["pack", "build", "chatgpt"],
5301 setup: &[],
5302 expect: Expect::StdoutContains(&["pack verify: clean"]),
5303 }],
5304 },
5305 CommandExamples {
5306 command: "pack verify",
5307 examples: &[ExampleDoc {
5308 id: "pack-verify-absent",
5309 title: "A directory that holds no pack",
5310 description: "A directory without a `pack.json` cannot be verified, and that is reported as unmeasured with exit 12 rather than as a clean pack: a verifier that passed what it could not read would pass anything.",
5311 argv: &["pack", "verify", "tmp/packs/absent"],
5312 setup: &[],
5313 expect: Expect::ExitCode(12),
5314 }],
5315 },
5316 CommandExamples {
5317 command: "shell check",
5318 examples: &[ExampleDoc {
5319 id: "shell-check-json",
5320 title: "Every shell unit against the automation inventory",
5321 description: "The shell units under the governed directories, how many records the inventory holds, the exemptions by disposition, and every finding with its remedy, as `/units`, `/exemptions`, `/findings` and `/passes`. The exit code is the verdict: 0 when every unit is declared and every record names a unit the tree still has, 10 on a finding, and 12 when the tree could not be measured, which is not a pass. Here the repository holds the bash library `lib/a.sh` and no inventory, so the answer is 10 and the finding names the file and the remedy.",
5322 argv: &["shell", "check", "--format", "json"],
5323 setup: &[],
5324 expect: Expect::ExitCode(10),
5325 }],
5326 },
5327 CommandExamples {
5328 command: "rules show",
5329 examples: &[ExampleDoc {
5330 id: "rules-show-absent",
5331 title: "A rule the repository does not declare",
5332 description: "A rule id nothing declares is a not-found rather than an empty answer. A typo that read as `this rule has no proof` is the one answer this command must never give, because it is indistinguishable from the finding the whole subsystem exists to report.",
5333 argv: &["rules", "show", "project.no-such-rule"],
5334 setup: &[],
5335 expect: Expect::ExitCode(12),
5336 }],
5337 },
5338 CommandExamples {
5339 command: "rules proves",
5340 examples: &[ExampleDoc {
5341 id: "rules-proves-case",
5342 title: "What a case proves, and what would lose its only proof",
5343 description: "The reverse of `rules show`, reading the same derivation so the two directions cannot disagree. It names every rule that names this test and, separately, the rules that would be left with no proof at all if it were deleted — the question to ask before renaming a case, and the one that could not be asked while the relation ran one way only.",
5344 argv: &["rules", "proves", "test/cases/125_rule_proof.sh", "--format", "json"],
5345 setup: &[],
5346 expect: Expect::Json(&["/proves", "/sole_proof_of", "/path"]),
5347 }],
5348 },
5349 CommandExamples {
5350 command: "continuity status",
5351 examples: &[ExampleDoc {
5352 id: "continuity-status-json",
5353 title: "Where this device stands in the work published from every device",
5354 description: "The same value `GET /api/v1/continuity/status` and the MCP tool `majordomus_continuity_status` return: this repository's identity (a digest of its root commits, the same in every clone), this device, the record this checkout continues on its branch, how the local store stands towards the remote's — read from refs, with no network — and what other devices published that could be resumed here. A repository that has published nothing answers with an empty store, which is an answer and not an error.",
5355 argv: &["continuity", "status", "--format", "json"],
5356 setup: &[],
5357 expect: Expect::Json(&["/repository", "/device/node", "/store/sync", "/resumable"]),
5358 }],
5359 },
5360 CommandExamples {
5361 command: "continuity device",
5362 examples: &[ExampleDoc {
5363 id: "continuity-device-json",
5364 title: "This device, as a published handover names it",
5365 description: "The node id and public key of this device's mesh key — created on first use in the user's state directory, never in a repository — and its label. `--label mac-mini` renames it without changing the key.",
5366 argv: &["continuity", "device", "--format", "json"],
5367 setup: &[],
5368 expect: Expect::Json(&["/device/node", "/device/label", "/public_key"]),
5369 }],
5370 },
5371 CommandExamples {
5372 command: "continuity records",
5373 examples: &[ExampleDoc {
5374 id: "continuity-records-json",
5375 title: "Every published handover, by line",
5376 description: "Every record of refs/majordomus/continuity that passed admission, every line of work with its heads, and a diagnostic for each refused file. Empty in a repository that has published nothing.",
5377 argv: &["continuity", "records", "--format", "json"],
5378 setup: &[],
5379 expect: Expect::Json(&["/records", "/lines", "/diagnostics"]),
5380 }],
5381 },
5382 CommandExamples {
5383 command: "continuity plan",
5384 examples: &[ExampleDoc {
5385 id: "continuity-plan-nothing",
5386 title: "A plan with nothing to resume",
5387 description: "With no handover published from another device, the plan says so — `nothing_to_resume` — and exits 0: absence is an answer. With one, the same command decides trust, lineage and source compatibility and lists the commands that resolve each blocker without running any of them.",
5388 argv: &["continuity", "plan", "--format", "json"],
5389 setup: &[],
5390 expect: Expect::Json(&["/status", "/blockers", "/warnings", "/actions"]),
5391 }],
5392 },
5393 CommandExamples {
5394 command: "continuity publish",
5395 examples: &[ExampleDoc {
5396 id: "continuity-publish-nothing",
5397 title: "Nothing to publish without a handover",
5398 description: "A publication reads the newest handover record; a checkout that has written none is told to write one with `majordomus handover` and exits 10, before any device key is created.",
5399 argv: &["continuity", "publish"],
5400 setup: &[],
5401 expect: Expect::ExitCode(10),
5402 }],
5403 },
5404 CommandExamples {
5405 command: "continuity sync",
5406 examples: &[ExampleDoc {
5407 id: "continuity-sync-no-remote",
5408 title: "A repository with no remote keeps its records",
5409 description: "Sync moves records only through a git remote. A repository with none answers `no_remote` and exits 0: the records stay in this clone, and that is a valid state rather than a failure.",
5410 argv: &["continuity", "sync", "--format", "json"],
5411 setup: &[],
5412 expect: Expect::Json(&["/action", "/store/sync"]),
5413 }],
5414 },
5415 CommandExamples {
5416 command: "continuity resume",
5417 examples: &[ExampleDoc {
5418 id: "continuity-resume-nothing",
5419 title: "A resume with nothing to resume writes nothing",
5420 description: "Resume acts only on a ready plan. With no published handover it writes nothing and exits 10, printing the plan that declined.",
5421 argv: &["continuity", "resume"],
5422 setup: &[],
5423 expect: Expect::ExitCode(10),
5424 }],
5425 },
5426 CommandExamples {
5427 command: "knowledge candidates",
5428 examples: &[ExampleDoc {
5429 id: "knowledge-candidates-json",
5430 title: "The review queue, as one document",
5431 description: "The same answer `GET /api/v1/knowledge/candidates`, the MCP tool `majordomus_knowledge_candidates` and the resource `majordomus://knowledge-candidates` serve: every record with status candidate under the candidates class, the branch of the episode each came from, how long each has waited, and the policy's cap beside the count. A repository whose deriver has not run yet answers with an empty queue, which is an answer and not an error.",
5432 argv: &["knowledge", "candidates", "--format", "json"],
5433 setup: &[],
5434 expect: Expect::Json(&["/total", "/on_this_branch", "/branch", "/over_cap"]),
5435 }],
5436 },
5437 CommandExamples {
5438 command: "knowledge record",
5439 examples: &[ExampleDoc {
5440 id: "knowledge-record-absent",
5441 title: "A record the repository does not hold",
5442 description: "An id nothing carries is a not-found rather than an empty answer, with the exit code that says which: a typo that read as `this record names no evidence` would be indistinguishable from the dangling reference the integrity validator exists to report.",
5443 argv: &["knowledge", "record", "no-such-record"],
5444 setup: &[],
5445 expect: Expect::ExitCode(12),
5446 }],
5447 },
5448 CommandExamples {
5449 command: "knowledge status",
5450 examples: &[ExampleDoc {
5451 id: "knowledge-status-json",
5452 title: "Whether the deriver is still writing",
5453 description: "The freshness half of the stopped-writer judgement: the newest derivation, the newest closed episode, how many closed episodes no derivation names, and — once a derivation has run in this checkout — whether the newest close went underived past the stale threshold. A fresh repository, in which no episode has closed, reports that it was not judged and why, and never a stopped writer.",
5454 argv: &["knowledge", "status", "--format", "json"],
5455 setup: &[],
5456 expect: Expect::Json(&["/present", "/judged", "/stopped_writer", "/freshness"]),
5457 }],
5458 },
5459 CommandExamples {
5460 command: "evidence record",
5461 examples: &[ExampleDoc {
5462 id: "evidence-record-missing",
5463 title: "Recording a report that is not there",
5464 description: "The recorder reads what a run already wrote — the suite's TSV report, `cargo test`'s output — and stamps it with the provenance the run did not carry. A report it cannot read is refused: recording nothing would leave every claim reading `not run` after a run that ran, which is a lie in the safe direction and still a lie.",
5465 argv: &["evidence", "record", "--suite", "target/no-such-run.tsv"],
5466 setup: &[],
5467 expect: Expect::ExitCode(13),
5468 }],
5469 },
5470 CommandExamples {
5471 command: "evidence stamp",
5472 examples: &[ExampleDoc {
5473 id: "evidence-stamp-json",
5474 title: "What a run measured, as one document",
5475 description: "The measurement a runner takes when its run ends: the commit, the tree with the evidence ledger ignored and the run's own untracked outputs excluded, the producer, its toolchain, the recorder's version and the host. `evidence record --provenance` carries it into the executions of that run's report.",
5476 argv: &["evidence", "stamp", "--producer", "suite", "--format", "json"],
5477 setup: &[],
5478 expect: Expect::Json(&["/producer", "/commit", "/working_tree", "/recorder", "/host"]),
5479 }],
5480 },
5481 CommandExamples {
5482 command: "served observe",
5483 examples: &[ExampleDoc {
5484 id: "served-observe-unreachable",
5485 title: "A deployment that could not be reached is not a deployment that is current",
5486 description: "One bounded probe of the build identity under the base URL, judged against HEAD. Nothing listens on the discard port, so nothing is received and the verdict is `unreachable` with exit 12 — the unanswered question, never the yes. `--dry-run` judges without recording. Against the public site the same command answers `served` (0) when the build contains the commit and `stale` (10) when it does not.",
5487 argv: &["served", "observe", "--url", "http://127.0.0.1:9", "--timeout", "1", "--dry-run"],
5488 setup: &[],
5489 expect: Expect::ExitCode(12),
5490 }],
5491 },
5492 CommandExamples {
5493 command: "served forge",
5494 examples: &[ExampleDoc {
5495 id: "served-forge-unknown-repository",
5496 title: "A forge that cannot be asked is said, and what was recorded before stands",
5497 description: "Asks the forge, through its own command-line tool, for the newest deployments to every environment and the newest releases, and records the answer `deploy.observed` reads. Here the repository has no remote the forge knows, so nothing is asked and the command says why with exit 12 — not answered, never an empty list read as none. In a checkout of a repository on the forge, with a credential, it prints how many deployments, environments and releases the answer held and exits 0.",
5498 argv: &["served", "forge"],
5499 setup: &[],
5500 expect: Expect::ExitCode(12),
5501 }],
5502 },
5503 CommandExamples {
5504 command: "served show",
5505 examples: &[ExampleDoc {
5506 id: "served-show-json",
5507 title: "What each deployment was last seen serving, judged against HEAD now",
5508 description: "The newest recorded observation of each deployment, re-judged against the commit asked about without probing anything. The same answer `GET /api/v1/served` and the MCP tool `majordomus_served` give. A checkout that has observed nothing answers with an empty list rather than a verdict.",
5509 argv: &["served", "show", "--format", "json"],
5510 setup: &[],
5511 expect: Expect::Json(&["/expected", "/observations", "/unreadable", "/deployments"]),
5512 }],
5513 },
5514 CommandExamples {
5515 command: "executions list",
5516 examples: &[ExampleDoc {
5517 id: "executions-list-json",
5518 title: "Every execution, as one document",
5519 description: "The same answer `GET /api/v1/executions`, the MCP tool `majordomus_executions` and the Cockpit's Executions page render, with the counts beside it: how many are remembered, how many are active, how many are waiting for a worker and how many live channels are following them.",
5520 argv: &["executions", "list", "--format", "json"],
5521 setup: &[],
5522 expect: Expect::Json(&["/count", "/active", "/queued", "/live_channels"]),
5523 }],
5524 },
5525 CommandExamples {
5526 command: "executions show",
5527 examples: &[ExampleDoc {
5528 id: "executions-show-absent",
5529 title: "An execution that is not there",
5530 description: "An execution lives in the process that accepted it and is remembered in bounded numbers, so asking for one nothing ran says so and exits with the missing-artifact code rather than inventing an empty answer. Against a running server, the same command prints that execution's state, its steps and what it produced.",
5531 argv: &["executions", "show", "x-20260101T120000Z-4c3b2a19"],
5532 setup: &[],
5533 expect: Expect::ExitCode(12),
5534 }],
5535 },
5536 CommandExamples {
5537 command: "executions events",
5538 examples: &[ExampleDoc {
5539 id: "executions-events-absent",
5540 title: "The events of an execution that is not there",
5541 description: "The retained events of one execution, oldest first, after a sequence number — what a reconnecting client reads before it opens the live channel. For an execution nothing ran, the same refusal as `show`.",
5542 argv: &["executions", "events", "x-20260101T120000Z-4c3b2a19"],
5543 setup: &[],
5544 expect: Expect::ExitCode(12),
5545 }],
5546 },
5547 CommandExamples {
5548 command: "executions cancel",
5549 examples: &[ExampleDoc {
5550 id: "executions-cancel-absent",
5551 title: "Asking an execution that is not there to stop",
5552 description: "Cancellation is cooperative: the flag is set and a task stops when it next looks at it. There is nothing to set for an execution nothing ran, and the command says so rather than reporting a success it did not have.",
5553 argv: &["executions", "cancel", "x-20260101T120000Z-4c3b2a19"],
5554 setup: &[],
5555 expect: Expect::ExitCode(12),
5556 }],
5557 },
5558 CommandExamples {
5559 command: "executions protocol",
5560 examples: &[ExampleDoc {
5561 id: "executions-protocol",
5562 title: "The live channel's contract, from the types that implement it",
5563 description: "Where the WebSocket is, how a subscription and a reconnect are expressed, every message type, and the JSON Schema of each — derived from the Rust types, so a client validating against this is validating against the implementation. OpenAPI cannot describe a socket, which is why this is a capability and not a paragraph.",
5564 argv: &["executions", "protocol", "--format", "json"],
5565 setup: &[],
5566 expect: Expect::Json(&["/protocol_version", "/websocket", "/event_types/0", "/stream_types/0", "/limits/max_events"]),
5567 }],
5568 },
5569 CommandExamples {
5570 command: "prs",
5571 examples: &[ExampleDoc {
5572 id: "prs-default-unobserved",
5573 title: "The queue, before the forge was ever observed",
5574 description: "`prs` with nothing after it is `prs status`. It reads the last recorded forge observation and never reaches the network, so in a checkout where `prs refresh` has never run it has nothing to rank: it says so, names the command that observes, and exits 10.",
5575 argv: &["prs"],
5576 setup: &[],
5577 expect: Expect::ExitCode(10),
5578 }],
5579 },
5580 CommandExamples {
5581 command: "prs status",
5582 examples: &[ExampleDoc {
5583 id: "prs-status-json-unobserved",
5584 title: "The ranked queue as one document",
5585 description: "Every open pull request's assessment in rank order — disposition, lane, reasons, the master and head it was decided against, evidence, risk, overlaps — with the next merge and the tallies. The same value `GET /api/v1/pull-requests` and the MCP tool `majordomus_pull_requests` answer. With no observation recorded it exits 10.",
5586 argv: &["prs", "status", "--format", "json"],
5587 setup: &[],
5588 expect: Expect::ExitCode(10),
5589 }],
5590 },
5591 CommandExamples {
5592 command: "prs plan",
5593 examples: &[ExampleDoc {
5594 id: "prs-plan-unobserved",
5595 title: "What the executor would do next",
5596 description: "The next merge, the pull requests that need master brought in, and the repair, cleanup and held lanes. The plan is void after any merge: the executor observes again before its next step. With no observation recorded it exits 10.",
5597 argv: &["prs", "plan"],
5598 setup: &[],
5599 expect: Expect::ExitCode(10),
5600 }],
5601 },
5602 CommandExamples {
5603 command: "prs explain",
5604 examples: &[ExampleDoc {
5605 id: "prs-explain-unobserved",
5606 title: "Why one pull request is where it is",
5607 description: "The revisions it was decided against, every piece of evidence, its rank and the factors behind it. The same answer `GET /api/v1/pull-requests/explain?number=` gives. With no observation recorded it exits 10.",
5608 argv: &["prs", "explain", "1"],
5609 setup: &[],
5610 expect: Expect::ExitCode(10),
5611 }],
5612 },
5613 CommandExamples {
5614 command: "prs events",
5615 examples: &[ExampleDoc {
5616 id: "prs-events-empty",
5617 title: "The audit trail of this checkout's executor",
5618 description: "Every selection, stale decision, merge with the master before and after, refusal, refresh and closure, oldest first. A checkout whose executor never ran has none, and says so.",
5619 argv: &["prs", "events"],
5620 setup: &[],
5621 expect: Expect::StdoutContains(&["no integration action"]),
5622 }],
5623 },
5624 CommandExamples {
5625 command: "prs trains",
5626 examples: &[ExampleDoc {
5627 id: "prs-trains-unobserved",
5628 title: "The trains of stacked pull requests, where nothing is observed",
5629 description: "Every open pull request stacked on another, grouped into trains in landing order, with each link's prepared head under refs/prep/<n> and whether it was pushed. The same answer `GET /api/v1/pull-requests/trains` gives and /cockpit/trains draws. With no observation recorded it says why and exits 10.",
5630 argv: &["prs", "trains"],
5631 setup: &[],
5632 expect: Expect::ExitCode(10),
5633 }],
5634 },
5635 CommandExamples {
5636 command: "prs refresh",
5637 examples: &[ExampleDoc {
5638 id: "prs-refresh-no-forge",
5639 title: "Observing the forge, where there is none",
5640 description: "`refresh` is one of the three `prs` commands that reach the network: it asks the GitHub CLI about the repository, its branch protection and its open pull requests, and fetches their heads. A repository with no GitHub remote cannot be observed, and the answer is exit 12 — unusable, never an empty queue.",
5641 argv: &["prs", "refresh"],
5642 setup: &[],
5643 expect: Expect::ExitCode(12),
5644 }],
5645 },
5646 CommandExamples {
5647 command: "prs drain",
5648 examples: &[ExampleDoc {
5649 id: "prs-drain-dry-run-no-forge",
5650 title: "A dry run starts from a fresh observation",
5651 description: "Even a dry run observes the forge first — a decision is never taken from the recorded observation — so where the forge cannot be reached it stops with exit 12 before deciding anything, and nothing is merged, refreshed or recorded.",
5652 argv: &["prs", "drain", "--dry-run"],
5653 setup: &[],
5654 expect: Expect::ExitCode(12),
5655 }],
5656 },
5657 CommandExamples {
5658 command: "prs prove-dry-run",
5659 examples: &[ExampleDoc {
5660 id: "prs-prove-dry-run-no-forge",
5661 title: "The proof needs a forge to prove anything about",
5662 description: "The proof snapshots origin's refs and the forge's open pull requests around refresh, plan, drain --dry-run and cleanup, and compares them. A repository with no GitHub remote has nothing to snapshot, so it exits 12 before any step runs: a proof that could not look is not a proof that nothing moved.",
5663 argv: &["prs", "prove-dry-run"],
5664 setup: &[],
5665 expect: Expect::ExitCode(12),
5666 }],
5667 },
5668 CommandExamples {
5669 command: "prs brief",
5670 examples: &[ExampleDoc {
5671 id: "prs-brief-unobserved",
5672 title: "The briefing line, where nothing was observed",
5673 description: "What `majordomus context` prints under INTEGRATION: the last queue this checkout built, the lease and the last merge, in one line, read from files and never from the network. A checkout whose forge was never observed has nothing to say, prints nothing, and exits 0 — a briefing does not grow a section about an empty queue.",
5674 argv: &["prs", "brief"],
5675 setup: &[],
5676 expect: Expect::ExitCode(0),
5677 }],
5678 },
5679 CommandExamples {
5680 command: "prs repair",
5681 examples: &[ExampleDoc {
5682 id: "prs-repair-unobserved",
5683 title: "A repair is decided on the recorded observation, or not at all",
5684 description: "The dry run, which is the default, is a read: it decides whether the named pull request may have master brought in from the queue the last recorded observation built, as `prs status` does, and reaches no network. Where nothing was ever observed there is no classification to decide from, so it exits 10 and names `prs refresh`; nothing is merged, pushed or recorded.",
5685 argv: &["prs", "repair", "1"],
5686 setup: &[],
5687 expect: Expect::ExitCode(10),
5688 }],
5689 },
5690 CommandExamples {
5691 command: "prs cleanup",
5692 examples: &[ExampleDoc {
5693 id: "prs-cleanup-no-forge",
5694 title: "Cleanup lists before it closes, and observes before it lists",
5695 description: "Without `--apply` cleanup only lists the pull requests whose work is provably on master; either way it observes the forge first, so where there is none it exits 12.",
5696 argv: &["prs", "cleanup"],
5697 setup: &[],
5698 expect: Expect::ExitCode(12),
5699 }],
5700 },
5701 CommandExamples {
5702 command: "convergence",
5703 examples: &[ExampleDoc {
5704 id: "convergence-report-json",
5705 title: "Is any work held where it can be lost?",
5706 description: "Every holding of this repository — a work tree with uncommitted files, a branch with commits, a stash — with the disposition read from git for each: integrated when the trunk reaches it, published when a remote-tracking ref does, local_only when nothing but this disk has it, uncommitted when it was never committed at all. The last two are at risk, and the verdict over them is what the completion invariant's `no-stale-topology` question reads. Measured offline: a remote-tracking ref is what this checkout last fetched, which is exactly the question — whether the work left this disk.",
5707 argv: &["convergence", "--format", "json"],
5708 setup: &[],
5709 expect: Expect::Json(&["/schema", "/converged", "/at_risk", "/tallies"]),
5710 }],
5711 },
5712 CommandExamples {
5713 command: "worktree",
5714 examples: &[ExampleDoc {
5715 id: "worktree-default-status",
5716 title: "Where am I, and is that where I belong?",
5717 description: "`worktree` with nothing after it answers the question a worker asks before starting: which branch this is, whether this directory is that branch's canonical worktree (or the primary checkout on the trunk), what is uncommitted here, and how many errors the whole topology carries. The same answer from the primary checkout and from four directories deep inside a linked worktree.",
5718 argv: &["worktree"],
5719 setup: &[],
5720 expect: Expect::StdoutContains(&["branch", "worktree", "container"]),
5721 }],
5722 },
5723 CommandExamples {
5724 command: "worktree status",
5725 examples: &[ExampleDoc {
5726 id: "worktree-status-json",
5727 title: "The current worktree as one document",
5728 description: "The same answer as JSON: the repository, the container, the trunk and how it was decided, this worktree with its standing and diagnostics, and whether it is where it belongs. This is what the MCP tool `majordomus_worktree_status` and `GET /api/v1/worktrees/status` answer.",
5729 argv: &["worktree", "status", "--format", "json"],
5730 setup: &[],
5731 expect: Expect::Json(&["/worktree/standing", "/container/path", "/trunk/source", "/canonical"]),
5732 }],
5733 },
5734 CommandExamples {
5735 command: "worktree list",
5736 examples: &[ExampleDoc {
5737 id: "worktree-list-text",
5738 title: "Every worktree, the misplaced ones obvious",
5739 description: "The primary checkout first, then every linked worktree with its standing, its branch, where it belongs when it is somewhere else, and its uncommitted work. The primary checkout is exempt from the path rule and held to the trunk rule instead.",
5740 argv: &["worktree", "list"],
5741 setup: &[&["worktree", "create", "feature/example"]],
5742 expect: Expect::StdoutContains(&["PRIMARY", "CANONICAL", "-wt/feature/example"]),
5743 }],
5744 },
5745 CommandExamples {
5746 command: "worktree topology",
5747 examples: &[ExampleDoc {
5748 id: "worktree-topology-json",
5749 title: "The whole topology as one document",
5750 description: "The repository, the container, the trunk, every worktree, every branch with or without a worktree, every diagnostic with its code and remedy, and the tallies. This is what the MCP resource `majordomus://worktrees`, the tool `majordomus_worktrees`, `GET /api/v1/worktrees` and the Cockpit all render.",
5751 argv: &["worktree", "topology", "--format", "json"],
5752 setup: &[],
5753 expect: Expect::Json(&["/container/path", "/trunk/branch", "/worktrees/0/standing", "/branches/0/name", "/tallies/worktrees", "/valid"]),
5754 }],
5755 },
5756 CommandExamples {
5757 command: "worktree root",
5758 examples: &[ExampleDoc {
5759 id: "worktree-root-path",
5760 title: "The container, for the shell",
5761 description: "Prints the container and nothing else, so a shell can use it: `cd \"$(majordomus worktree root)\"`. It is the primary checkout's sibling named with `-wt`, derived from git's own identity and never from the current directory — which is why running this inside a linked worktree does not answer a container inside that worktree.",
5762 argv: &["worktree", "root"],
5763 setup: &[],
5764 expect: Expect::StdoutContains(&["-wt"]),
5765 }],
5766 },
5767 CommandExamples {
5768 command: "worktree path",
5769 examples: &[ExampleDoc {
5770 id: "worktree-path-branch",
5771 title: "The canonical path of a branch, for the shell",
5772 description: "A child process cannot change its parent shell's directory, so nothing here pretends to: this prints one path and the shell does the rest — `cd \"$(majordomus worktree path feature/x)\"`. The path is the branch name under the container, hierarchy kept; the branch need not exist yet.",
5773 argv: &["worktree", "path", "feature/providers/streaming"],
5774 setup: &[],
5775 expect: Expect::StdoutContains(&["-wt/feature/providers/streaming"]),
5776 }],
5777 },
5778 CommandExamples {
5779 command: "worktree inspect",
5780 examples: &[ExampleDoc {
5781 id: "worktree-inspect-branch",
5782 title: "One branch, before creating its worktree",
5783 description: "Where the branch's worktree belongs, whether the branch exists, whether anything occupies the path, and what would stand in the way. For a branch that does not exist yet, the answer is the path `worktree create` would use and the command to run.",
5784 argv: &["worktree", "inspect", "feature/new-dashboard"],
5785 setup: &[],
5786 expect: Expect::StdoutContains(&["-wt/feature/new-dashboard", "does not exist yet"]),
5787 }],
5788 },
5789 CommandExamples {
5790 command: "worktree create",
5791 examples: &[ExampleDoc {
5792 id: "worktree-create-branch",
5793 title: "Start work on a branch without deciding where it goes",
5794 description: "Creates the branch `feature/improve-cli` from the trunk and checks it out in a new worktree at `<repository>-wt/feature/improve-cli`. No path is given and none may be: the destination follows from the repository's identity and the branch name, so the same command in the same repository always produces the same path — from the primary checkout, and from inside another worktree.",
5795 argv: &["worktree", "create", "feature/improve-cli"],
5796 setup: &[],
5797 expect: Expect::StdoutContains(&["-wt/feature/improve-cli", "feature/improve-cli (new"]),
5798 }],
5799 },
5800 CommandExamples {
5801 command: "worktree ensure",
5802 examples: &[ExampleDoc {
5803 id: "worktree-ensure-existing",
5804 title: "The canonical worktree, whether or not it exists yet",
5805 description: "`ensure` is `create` for a caller that does not care whether the worktree is already there: it creates it when it is absent and answers the existing one when it is present. What a script or an agent runs before starting on a branch.",
5806 argv: &["worktree", "ensure", "feature/improve-cli"],
5807 setup: &[&["worktree", "create", "feature/improve-cli"]],
5808 expect: Expect::StdoutContains(&["exists", "-wt/feature/improve-cli"]),
5809 }],
5810 },
5811 CommandExamples {
5812 command: "worktree migrate",
5813 examples: &[ExampleDoc {
5814 id: "worktree-migrate-plan",
5815 title: "What it would take to bring every worktree home",
5816 description: "`--plan` shows each misplaced worktree with where it belongs, how it would move, the uncommitted work that moves with it, and what blocks it, and changes nothing. Without `--plan` the movable steps are carried out: each worktree is fingerprinted, moved with `git worktree move`, fingerprinted again at its new path, and reported as moved only when the two are equal.",
5817 argv: &["worktree", "migrate", "--plan"],
5818 setup: &[],
5819 expect: Expect::StdoutContains(&["nothing to migrate"]),
5820 }],
5821 },
5822 CommandExamples {
5823 command: "worktree validate",
5824 examples: &[ExampleDoc {
5825 id: "worktree-validate-clean",
5826 title: "Is the topology valid?",
5827 description: "Every error-level diagnostic and nothing else, then the verdict; exit 10 when there is an error. What a script gates on.",
5828 argv: &["worktree", "validate"],
5829 setup: &[],
5830 expect: Expect::StdoutContains(&["worktree topology: valid"]),
5831 }],
5832 },
5833 CommandExamples {
5834 command: "worktree doctor",
5835 examples: &[ExampleDoc {
5836 id: "worktree-doctor-clean",
5837 title: "Every diagnostic, with its code and its remedy",
5838 description: "Errors, warnings and facts — a misplaced worktree, a stale registration, a detached HEAD, the primary checkout off the trunk, an unknown trunk — each under a stable code the API and the Cockpit carry too, each with the command that addresses it.",
5839 argv: &["worktree", "doctor"],
5840 setup: &[],
5841 expect: Expect::StdoutContains(&["worktree topology: valid"]),
5842 }],
5843 },
5844 CommandExamples {
5845 command: "worktree guard",
5846 examples: &[ExampleDoc {
5847 id: "worktree-guard-ok",
5848 title: "May a commit proceed from here?",
5849 description: "The pre-commit hook's question. Exit 0 in a branch's canonical worktree, in the primary checkout on the trunk, or on a detached HEAD; exit 10 with the diagnostic and the remedy when a feature branch is being worked on somewhere it does not belong. The hook stays one line; this is the logic.",
5850 argv: &["worktree", "guard"],
5851 setup: &[],
5852 expect: Expect::StdoutContains(&["worktree guard: ok"]),
5853 }],
5854 },
5855 CommandExamples {
5856 command: "worktree repair",
5857 examples: &[ExampleDoc {
5858 id: "worktree-repair-dry-run",
5859 title: "What git would forget",
5860 description: "`repair` drops git's registrations of worktrees whose directories no longer exist and lets git repair the administrative links of the ones that do. It deletes no directory and touches no branch; `--dry-run` reports what it would drop and changes nothing.",
5861 argv: &["worktree", "repair", "--dry-run"],
5862 setup: &[],
5863 expect: Expect::StdoutContains(&["nothing to prune"]),
5864 }],
5865 },
5866 CommandExamples {
5867 command: "worktree remove",
5868 examples: &[ExampleDoc {
5869 id: "worktree-remove-clean",
5870 title: "Remove a worktree, and keep its branch",
5871 description: "Removes the worktree and nothing else. The branch it held still exists: worktree lifecycle and branch lifecycle are separate, and deleting a branch is a git command a person types deliberately. A worktree with uncommitted work is refused rather than removed.",
5872 argv: &["worktree", "remove", "feature/improve-cli"],
5873 setup: &[&["worktree", "create", "feature/improve-cli"]],
5874 expect: Expect::StdoutContains(&["removed", "feature/improve-cli still exists"]),
5875 }],
5876 },
5877 CommandExamples {
5878 command: "worktree cleanup",
5879 examples: &[ExampleDoc {
5880 id: "worktree-cleanup-nothing",
5881 title: "What could go, and what it would take",
5882 description: "Every branch merged into the trunk whose worktree is clean or absent, with the two commands that would remove the worktree and then the branch. Derived state only: nothing is deleted here, and a dirty or unmerged worktree is never listed.",
5883 argv: &["worktree", "cleanup"],
5884 setup: &[],
5885 expect: Expect::StdoutContains(&["cleanup-eligible"]),
5886 }],
5887 },
5888 CommandExamples {
5889 command: "worktree uncommitted",
5890 examples: &[ExampleDoc {
5891 id: "worktree-uncommitted-none",
5892 title: "Work no commit carries, and whether anything holds it",
5893 description: "Every linked worktree holding staged, unstaged, untracked or conflicted paths, with the count, the age of the oldest change, the task, episode or process that holds it, and `abandoned` when nothing does and it is older than the policy's session.stranded_after. A repository with no linked worktree has nothing to list; the reading writes nothing either way.",
5894 argv: &["worktree", "uncommitted"],
5895 setup: &[],
5896 expect: Expect::StdoutContains(&["0 with uncommitted work", "nothing was changed"]),
5897 }],
5898 },
5899 CommandExamples {
5900 command: "worktree branches",
5901 examples: &[ExampleDoc {
5902 id: "worktree-branches-list",
5903 title: "The live branch set, for completion",
5904 description: "Every local branch, one per line, nothing else. A shell completion for `worktree path`, `create` or `remove` reads this rather than a list kept anywhere, so a branch created a second ago completes.",
5905 argv: &["worktree", "branches"],
5906 setup: &[],
5907 expect: Expect::Success,
5908 }],
5909 },
5910 CommandExamples {
5911 command: "distribution",
5912 examples: &[ExampleDoc {
5913 id: "distribution-show-default",
5914 title: "How this project is installed",
5915 description: "`distribution` with nothing after it shows the model: the one-line install command, where an installation goes, and how many platforms a release builds. Every value comes from share/distribution.yaml, which is the only place any of them is written.",
5916 argv: &["distribution"],
5917 setup: &[],
5918 expect: Expect::StdoutContains(&["binary", "install", "targets"]),
5919 }],
5920 },
5921 CommandExamples {
5922 command: "distribution show",
5923 examples: &[ExampleDoc {
5924 id: "distribution-show-json",
5925 title: "The distribution model as one JSON document",
5926 description: "The same answer as a document a script can read: the install command, the default locations, and every declared target with the artifact name the naming function derives for it. This is what the website's install block and the cockpit's install card render.",
5927 argv: &["distribution", "show", "--format", "json"],
5928 setup: &[],
5929 expect: Expect::Json(&["/install_command", "/targets"]),
5930 }],
5931 },
5932 CommandExamples {
5933 command: "distribution targets",
5934 examples: &[ExampleDoc {
5935 id: "distribution-targets",
5936 title: "Every platform, and whether a release builds it",
5937 description: "One line per declared target: its id, its Rust target triple, whether it is supported, experimental or unavailable, and how it is written in prose. The supported-platform table in the documentation and the installer's own refusal message are rendered from these same rows.",
5938 argv: &["distribution", "targets"],
5939 setup: &[],
5940 expect: Expect::StdoutContains(&["RUST TARGET", "supported"]),
5941 }],
5942 },
5943 CommandExamples {
5944 command: "distribution validate",
5945 examples: &[ExampleDoc {
5946 id: "distribution-validate",
5947 title: "Every invariant of the model and of the release records",
5948 description: "Refuses a duplicate target id or triple, two targets deriving one artifact name, a Linux target with no C library, a published target with nothing to build it on, an unbuilt target with no recorded reason, a base URL that is not HTTPS, and a release record that misses a supported target, renames an artifact or serves one from another host. Exits 10 with each violation named.",
5949 argv: &["distribution", "validate"],
5950 setup: &[],
5951 expect: Expect::StdoutContains(&["distribution"]),
5952 }],
5953 },
5954 CommandExamples {
5955 command: "distribution matrix",
5956 examples: &[ExampleDoc {
5957 id: "distribution-matrix",
5958 title: "The release build matrix the workflow runs",
5959 description: "One entry per published target, with the runner it is built on, the packages that runner needs, and the artifact name with `{tag}` where a release's tag goes. The release workflow reads this and states no platform of its own; adding a target to the model adds a build here and nowhere else.",
5960 argv: &["distribution", "matrix"],
5961 setup: &[],
5962 expect: Expect::Json(&["/include", "/binary"]),
5963 }],
5964 },
5965 CommandExamples {
5966 command: "distribution artifact",
5967 examples: &[ExampleDoc {
5968 id: "distribution-artifact",
5969 title: "What one target and one tag are called",
5970 description: "The one naming function, asked directly: the archive's name, the directory it unpacks into, and where a release publishes it. `scripts/release-package` asks this rather than composing a name, so a change to the naming function reaches the packaging without an edit.",
5971 argv: &["distribution", "artifact", "--target", "aarch64-apple-darwin", "--tag", "v0.2.0", "--format", "json"],
5972 setup: &[],
5973 expect: Expect::Json(&["/name", "/root", "/url"]),
5974 }],
5975 },
5976 CommandExamples {
5977 command: "distribution status",
5978 examples: &[ExampleDoc {
5979 id: "distribution-status",
5980 title: "Whether the published one-line installation works right now",
5981 description: "The operator's question — *can a machine that has never seen this project install it with the advertised command?* — answered from the distribution model and the release records, without touching the network. Each check names what was observed; a failing one names its cause and the command that changes it. Shown here in a repository that has published nothing, where the answer is no and the exit code is 10, which is what makes it usable as a check rather than as prose. `distribution validate` is the gate over the model itself; this is the gate over the state a user meets.",
5982 argv: &["distribution", "status"],
5983 setup: &[],
5984 expect: Expect::ExitCode(10),
5985 }],
5986 },
5987 CommandExamples {
5988 command: "distribution releases",
5989 examples: &[ExampleDoc {
5990 id: "distribution-releases",
5991 title: "What has been published, and what an unpinned install resolves to",
5992 description: "Every release record this repository holds, newest first, and which of them the stable pointer names: the highest version among the stable, unwithdrawn records. The pointer is derived on every read and is authored nowhere.",
5993 argv: &["distribution", "releases"],
5994 setup: &[],
5995 expect: Expect::Success,
5996 }],
5997 },
5998 CommandExamples {
5999 command: "distribution metadata",
6000 examples: &[ExampleDoc {
6001 id: "distribution-metadata",
6002 title: "What one release record publishes",
6003 description: "The public metadata a record turns into, rendered from the record and the model alone: the release pipeline prints this before it commits anything, and the installer's own tests serve it as a release that never existed. Shown here in a repository that has published nothing, where the record does not exist and the command says which file it wanted and exits 10 rather than inventing one.",
6004 argv: &["distribution", "metadata", "--record", ".ai/repo/releases/v0.2.0.yaml"],
6005 setup: &[],
6006 expect: Expect::ExitCode(10),
6007 }],
6008 },
6009 CommandExamples {
6010 command: "distribution build",
6011 examples: &[ExampleDoc {
6012 id: "distribution-build",
6013 title: "What this executable is",
6014 description: "The crate version, the Rust target triple, the profile and the commit, all compiled in at build time. An installed binary answers this without a repository, a toolchain or git, which is what makes a support question answerable.",
6015 argv: &["distribution", "build"],
6016 setup: &[],
6017 expect: Expect::StdoutContains(&["version", "target", "commit"]),
6018 }],
6019 },
6020 CommandExamples {
6021 command: "mcp",
6022 examples: &[
6023 ExampleDoc {
6024 id: "mcp-inspect",
6025 title: "See what would be served, without serving it",
6026 description: "Builds the registry and the index of the repository in the working directory and prints the repository, the capabilities, the objects and every diagnostic, then exits. Nothing is served and nothing is written.",
6027 argv: &["mcp", "--inspect"],
6028 setup: &[],
6029 expect: Expect::StdoutContains(&["repository", "capabilities"]),
6030 },
6031 ExampleDoc {
6032 id: "mcp-inspect-json",
6033 title: "The same, as one JSON document for a script",
6034 description: "The shape `--inspect` prints for a person, as JSON: the repository, its discovery mode, the capabilities and the diagnostics, deterministic and safe to diff.",
6035 argv: &["mcp", "--inspect", "--format", "json"],
6036 setup: &[],
6037 expect: Expect::Json(&["/repository/repository/root", "/tools"]),
6038 },
6039 ExampleDoc {
6040 id: "mcp-stdio",
6041 title: "Serve one MCP client on stdio",
6042 description: "The form an MCP client spawns: JSON-RPC frames in on stdin, frames out on stdout, logs on stderr, and the session ends at end of input. `--standalone` keeps this process to itself: no shared server, no HTTP, nothing written anywhere.",
6043 argv: &["mcp", "--standalone"],
6044 setup: &[],
6045 expect: Expect::McpReady,
6046 },
6047 ],
6048 },
6049 CommandExamples {
6050 command: "web list",
6051 examples: &[ExampleDoc {
6052 id: "web-list",
6053 title: "Every web surface this repository exposes",
6054 description: "The resolved topology, in route-precedence order: the routes the executable answers itself, the application's site, and every generated report that declared itself under the generated web root. Nothing is registered anywhere; each line was discovered.",
6055 argv: &["web", "list"],
6056 setup: &[],
6057 expect: Expect::StdoutContains(&["MOUNT", "/api/v1", "/swagger"]),
6058 }],
6059 },
6060 CommandExamples {
6061 command: "web",
6062 examples: &[ExampleDoc {
6063 id: "web-topology",
6064 title: "The topology, from the command with no subcommand",
6065 description: "`web` with nothing after it lists, because listing is what a person wants when they ask what this repository exposes.",
6066 argv: &["web"],
6067 setup: &[],
6068 expect: Expect::StdoutContains(&["ID", "MOUNT"]),
6069 }],
6070 },
6071 CommandExamples {
6072 command: "web explain",
6073 examples: &[ExampleDoc {
6074 id: "web-explain",
6075 title: "Why a surface exists and where each of its values came from",
6076 description: "For each field a reader could be surprised by — the mount, the kind, the directory — the source that decided it: a producer's own declaration, the site configuration, the capability registry, or the model's documented default.",
6077 argv: &["web", "explain", "swagger"],
6078 setup: &[],
6079 expect: Expect::StdoutContains(&["swagger", "came from"]),
6080 }],
6081 },
6082 CommandExamples {
6083 command: "web validate",
6084 examples: &[ExampleDoc {
6085 id: "web-validate",
6086 title: "Check the topology before anything serves or publishes it",
6087 description: "Two surfaces claiming one path, a surface nested inside another's subtree, a directory outside the generated root or one that walks out of the repository: each is a named finding with the surface, the value, its source and the fix. Exit 10 on any error finding. `--artifacts` also requires every static surface's directory and index to exist, which is what serving and publishing need.",
6088 argv: &["web", "validate"],
6089 setup: &[],
6090 expect: Expect::StdoutContains(&["no conflict"]),
6091 }],
6092 },
6093 CommandExamples {
6094 command: "web manifest",
6095 examples: &[ExampleDoc {
6096 id: "web-manifest",
6097 title: "Write the resolved topology down for another tool to read",
6098 description: "The manifest under the generated web root is derived state: a publisher or a CI job may read it instead of resolving the topology again, and nothing may edit it, because the next run overwrites it from the same discovery.",
6099 argv: &["web", "manifest"],
6100 setup: &[],
6101 expect: Expect::StdoutContains(&["web manifest", "surface"]),
6102 }],
6103 },
6104 CommandExamples {
6105 command: "web report tests",
6106 examples: &[ExampleDoc {
6107 id: "web-report-tests",
6108 title: "Render the suite's own results into the /tests surface",
6109 description: "The runner writes its report with `MJ_TEST_REPORT=<file> bash test/run.sh`; this renders it, keeps the machine-readable results beside the page, and declares the directory so discovery finds it. Without that file there is nothing to render and the command says so rather than publishing an empty page.",
6110 argv: &["web", "report", "tests", "--suite", "target/web/run.tsv"],
6111 setup: &[],
6112 expect: Expect::ExitCode(13),
6113 }],
6114 },
6115 CommandExamples {
6116 command: "web report benchmarks",
6117 examples: &[ExampleDoc {
6118 id: "web-report-benchmarks",
6119 title: "Render a benchmark run into the /benchmarks surface",
6120 description: "Reads a results document — a run's own output, or an accepted baseline under the layer's benchmarks section, which have the same shape — and renders every measured target ordered by median. It measures nothing itself: a figure on the page is a figure a run produced.",
6121 argv: &[
6122 "web", "report", "benchmarks",
6123 "--from", ".ai/repo/benchmarks/rust/baseline.macos-aarch64-debug.json",
6124 ],
6125 setup: &[],
6126 expect: Expect::ExitCode(13),
6127 }],
6128 },
6129 CommandExamples {
6130 command: "web report ui",
6131 examples: &[ExampleDoc {
6132 id: "web-report-ui",
6133 title: "Render the UI conformance audit into /tests/ui",
6134 description: "`scripts/ui audit` drives a browser over every page of the built site at every width the compiled stylesheet's breakpoints imply, and writes one results document; this renders it. The rendering is a section of the test surface rather than a surface of its own, because a conformance run is a test run and the topology refuses a surface mounted inside another's subtree. Without that document there is nothing to render and the command says so.",
6135 argv: &["web", "report", "ui", "--from", "target/web/run-ui.json"],
6136 setup: &[],
6137 expect: Expect::ExitCode(13),
6138 }],
6139 },
6140 CommandExamples {
6141 command: "web report ui-snapshot",
6142 examples: &[ExampleDoc {
6143 id: "web-report-ui-snapshot",
6144 title: "Read the UI once and write it as the pages a publication carries at /ui",
6145 description: "Asks the UI in-process for every screen and panel and then, one page per family in turn until `--limit` pages or `--budget-seconds` are reached, for the pages they link to, and writes each as a file under target/web/ui-snapshot: links between them relative, a link only a running process answers led to the snapshot's page about the live UI, the script told not to read again, and every page stamped with the commit, the time and the executable that read it. The declaration beside it makes the directory a surface of every publication and of no process.",
6146 argv: &["web", "report", "ui-snapshot", "--limit", "20"],
6147 setup: &[],
6148 expect: Expect::StdoutContains(&["web report", "ui-snapshot"]),
6149 }],
6150 },
6151 CommandExamples {
6152 command: "web report cockpit-snapshot",
6153 examples: &[ExampleDoc {
6154 id: "web-report-cockpit-snapshot",
6155 title: "Read the Cockpit once and write it as the pages a publication carries at /cockpit",
6156 description: "Asks the Cockpit in-process for every static route except the one page about this machine, then for the pages the UI's snapshot links to, then, one page per family in turn until `--limit` pages or `--budget-seconds` are reached, for the pages those link to, and writes each as a file under target/web/cockpit-snapshot. Links between them are relative; a link into the UI leads to the UI's snapshot when that holds the page; a form, a query or a page past the bound leads to the snapshot's page about the live Cockpit; no page carries a script, because the Cockpit's scripts talk to a process; and every page is stamped with the commit, the time and the executable that read it.",
6157 argv: &["web", "report", "cockpit-snapshot", "--limit", "12"],
6158 setup: &[],
6159 expect: Expect::StdoutContains(&["web report", "cockpit-snapshot"]),
6160 }],
6161 },
6162 CommandExamples {
6163 command: "web compose",
6164 examples: &[ExampleDoc {
6165 id: "web-compose",
6166 title: "Compose every published surface into one publishable tree",
6167 description: "Each producer owns its own output directory; publication needs one tree, and the mapping is the resolved mount and nothing else. A surface that is discovered is published without a copy step being written anywhere, and a repository with nothing generated yet composes an empty tree rather than an error. Where a surface exists and its directory does not, composition refuses and names the producer to run.",
6168 argv: &["web", "compose", "--destination", "target/site"],
6169 setup: &[],
6170 expect: Expect::Success,
6171 }],
6172 },
6173 CommandExamples {
6174 command: "devtask issue",
6175 examples: &[
6176 ExampleDoc {
6177 id: "devtask-issue",
6178 title: "One issue as work to be done, not as metadata",
6179 description: "Identity, intent, status, milestone, dependencies, blockers, branches, commits, sessions and readiness in one answer, composed from the derivations that already own each half — the plan for the graph, `trace` for git, the canonical record for everything a person wrote. Nothing is manufactured: a key the record does not carry is `unknown` with the reason, never an empty string that reads as authored.",
6180 argv: &["devtask", "issue", "I0001"],
6181 setup: &[],
6182 expect: Expect::StdoutContains(&["readiness", "explicit"]),
6183 },
6184 ExampleDoc {
6185 id: "devtask-issue-json",
6186 title: "The same, as the shape the API and MCP answer with",
6187 description: "One domain model behind every projection: this document is what `GET /api/v1/devtask/issue` returns and what the `majordomus_devtask` tool answers, with the four groups kept apart by the type — what a person authored, what the plan derives, what happened locally, and where the external projection stands — and a provenance on every field.",
6188 argv: &["devtask", "issue", "I0001", "--no-git", "--format", "json"],
6189 setup: &[],
6190 expect: Expect::Json(&[
6191 "/declaration/title/provenance",
6192 "/position/status/provenance",
6193 "/readiness/state",
6194 "/attestation/explicit",
6195 ]),
6196 },
6197 ExampleDoc {
6198 id: "devtask-issue-undeclared",
6199 title: "An id the model does not declare is answered, not refused",
6200 description: "A typo that read as \"nothing has been authored\" is the one answer a work surface must never give, so an unknown id answers with `declared: false`, the readiness `undeclared`, and every canonical field `unknown` with the reason on it.",
6201 argv: &["devtask", "issue", "I9999", "--no-git"],
6202 setup: &[],
6203 expect: Expect::StdoutContains(&["undeclared"]),
6204 },
6205 ],
6206 },
6207 CommandExamples {
6208 command: "devtask milestone",
6209 examples: &[
6210 ExampleDoc {
6211 id: "devtask-milestone",
6212 title: "What to work on next in one outcome, and what to unblock first",
6213 description: "The issues partitioned by readiness, the critical blockers ordered by how much unfinished work each holds back, and the startable work partitioned into subsets that may genuinely run at the same time. A pure function of the canonical records — no git, no clock, no network — so two runs on two machines produce the same bytes and a reader derives nothing itself.",
6214 argv: &["devtask", "milestone", "foundation"],
6215 setup: &[],
6216 expect: Expect::StdoutContains(&["READINESS"]),
6217 },
6218 ExampleDoc {
6219 id: "devtask-milestone-json",
6220 title: "The graph, as the shape the API and MCP answer with",
6221 description: "Every partition the plan implies and no surface should recompute: `ready`, `blocked`, `waiting`, `active`, `review`, `completion_blocked`, `complete`, `cancelled`, plus `critical_blockers`, `parallelizable` with the scope path behind each serialisation, and `cycles` as strongly connected components.",
6222 argv: &["devtask", "milestone", "foundation", "--format", "json"],
6223 setup: &[],
6224 expect: Expect::Json(&["/counts/total", "/ready", "/critical_blockers", "/parallelizable"]),
6225 },
6226 ],
6227 },
6228 CommandExamples {
6229 command: "why",
6230 examples: &[ExampleDoc {
6231 id: "why-catalogue",
6232 title: "The operational moments this repository holds",
6233 description: "`why` with nothing after it lists, because listing is what a person wants when they ask what this section is. The count on the last line is computed from the catalogue; no number anywhere is written down.",
6234 argv: &["why"],
6235 setup: &[],
6236 expect: Expect::StdoutContains(&["SLUG", "moment(s)"]),
6237 }],
6238 },
6239 CommandExamples {
6240 command: "skills status",
6241 examples: &[
6242 ExampleDoc {
6243 id: "skills-status",
6244 title: "Every skill, with its derived standing",
6245 description: "Tested, documented, enforced and used are derived on every read from the tests that name the skill, the evidence ledger, the site projection, the CI model and the invocation surfaces; no file stores them. A repository with no skill answers with none.",
6246 argv: &["skills", "status"],
6247 setup: &[],
6248 expect: Expect::StdoutContains(&["skill(s)"]),
6249 },
6250 ExampleDoc {
6251 id: "skills-status-json",
6252 title: "The same, as the shape the API and MCP answer with",
6253 description: "What `GET /api/v1/skills` returns and the `majordomus_skills` tool answers: the count, the tally by standing, and every skill with its four derived facts.",
6254 argv: &["skills", "status", "--format", "json"],
6255 setup: &[],
6256 expect: Expect::Json(&["/count", "/standings", "/skills"]),
6257 },
6258 ],
6259 },
6260 CommandExamples {
6261 command: "skills explain",
6262 examples: &[ExampleDoc {
6263 id: "skills-explain-absent",
6264 title: "A skill the repository does not hold is a refusal, not an empty answer",
6265 description: "`skills explain <id>` answers one skill in full: each naming test with the state of its latest run and how to reproduce it, its page, its gates and every invocation by path and line. An id that names no skill exits 12 and names what was looked for.",
6266 argv: &["skills", "explain", "no-such-skill"],
6267 setup: &[],
6268 expect: Expect::ExitCode(12),
6269 }],
6270 },
6271 CommandExamples {
6272 command: "skills verify",
6273 examples: &[ExampleDoc {
6274 id: "skills-verify",
6275 title: "Check every skill is a proven capability",
6276 description: "An active skill no test names or nothing invokes, a failing run, a contract violation, or a test or invocation naming a skill that does not exist: each a failure, and exit 10. Evidence that is not current, a missing page or a missing gate: a warning.",
6277 argv: &["skills", "verify"],
6278 setup: &[],
6279 expect: Expect::StdoutContains(&["skill(s)", "valid"]),
6280 }],
6281 },
6282 CommandExamples {
6283 command: "why list",
6284 examples: &[
6285 ExampleDoc {
6286 id: "why-list",
6287 title: "Every public moment, in presentation order",
6288 description: "Drafts are excluded unless `--all` is given. The facets a listing may be narrowed by are the ones the catalogue itself reports, so an audience or an area added as a file is a filter without anything being registered.",
6289 argv: &["why", "list"],
6290 setup: &[],
6291 expect: Expect::StdoutContains(&["SLUG"]),
6292 },
6293 ExampleDoc {
6294 id: "why-list-audience",
6295 title: "Only what one audience recognises",
6296 description: "Membership is declared by each moment and never listed in the audience's own file, so this answer is derived. An audience the catalogue does not have is an invalid input naming the ones it does, not an empty answer.",
6297 argv: &["why", "list", "--audience", "fixture-team"],
6298 setup: &[],
6299 expect: Expect::StdoutContains(&["SLUG"]),
6300 },
6301 ExampleDoc {
6302 id: "why-list-json",
6303 title: "The same, as the shape the API and MCP answer with",
6304 description: "One domain model behind every projection: this document is what `GET /api/v1/why` returns and what the `majordomus_why` tool answers, including the derived facets and the catalogue's fingerprint.",
6305 argv: &["why", "list", "--format", "json"],
6306 setup: &[],
6307 expect: Expect::Json(&["/counts/moments", "/facets/audiences", "/fingerprint"]),
6308 },
6309 ],
6310 },
6311 CommandExamples {
6312 command: "why show",
6313 examples: &[ExampleDoc {
6314 id: "why-show",
6315 title: "One moment, with every relation derived from its metadata",
6316 description: "The record as its file declares it, then what nobody authored: the responsibilities its claims belong to, the moments that name it, and the moments nearest it by shared area, audience and tag.",
6317 argv: &["why", "show", "fixture-moment"],
6318 setup: &[],
6319 expect: Expect::StdoutContains(&["fixture-moment", "derived"]),
6320 }],
6321 },
6322 CommandExamples {
6323 command: "why audiences",
6324 examples: &[ExampleDoc {
6325 id: "why-audiences",
6326 title: "Who recognises what, with the counts derived",
6327 description: "Each audience with how many public moments name it. The number is computed from the moments; an audience's own file never lists one.",
6328 argv: &["why", "audiences"],
6329 setup: &[],
6330 expect: Expect::StdoutContains(&["SLUG", "TITLE"]),
6331 }],
6332 },
6333 CommandExamples {
6334 command: "why areas",
6335 examples: &[ExampleDoc {
6336 id: "why-areas",
6337 title: "The operational areas, with the counts derived",
6338 description: "The same relation read the other way: each area with the public moments that fall under it.",
6339 argv: &["why", "areas"],
6340 setup: &[],
6341 expect: Expect::StdoutContains(&["SLUG", "TITLE"]),
6342 }],
6343 },
6344 CommandExamples {
6345 command: "why diagnose",
6346 examples: &[
6347 ExampleDoc {
6348 id: "why-diagnose-questions",
6349 title: "The questionnaire, assembled from the catalogue's own signals",
6350 description: "With no selection there is nothing to diagnose, so the questions are printed instead of an empty answer. Every line is a signal a moment declares; nothing here is a list of questions.",
6351 argv: &["why", "diagnose"],
6352 setup: &[],
6353 expect: Expect::StdoutContains(&["Which of these happened to you this week?"]),
6354 },
6355 ExampleDoc {
6356 id: "why-diagnose",
6357 title: "What the symptoms you recognise imply",
6358 description: "A name is a signal id or a moment id. The answer is counting, not inference: each recommendation carries the moments that produced it, and there is no percentage because there is no model behind one.",
6359 argv: &["why", "diagnose", "--signal", "fixture-signal"],
6360 setup: &[],
6361 expect: Expect::StdoutContains(&["moment(s) matched", "fixture-moment"]),
6362 },
6363 ],
6364 },
6365 CommandExamples {
6366 command: "why validate",
6367 examples: &[ExampleDoc {
6368 id: "why-validate",
6369 title: "Check the catalogue before anything projects it",
6370 description: "A reference that resolves to nothing, with the nearest candidate; a duplicate identity; a file name that disagrees with its id; a public record that does not meet the floor its status promises. Exit 10 on any error.",
6371 argv: &["why", "validate"],
6372 setup: &[],
6373 expect: Expect::StdoutContains(&["moment(s)", "valid"]),
6374 }],
6375 },
6376 CommandExamples {
6377 command: "intent list",
6378 examples: &[
6379 ExampleDoc {
6380 id: "intent-list",
6381 title: "Every intent, with its derived stage",
6382 description: "The stage is derived on every read from the status the plan gives each milestone the intent names and from the evidence recorded for each criterion; no file stores it.",
6383 argv: &["intent", "list"],
6384 setup: &[],
6385 expect: Expect::StdoutContains(&["STAGE", "intent(s)"]),
6386 },
6387 ExampleDoc {
6388 id: "intent-list-json",
6389 title: "The same, as the shape the API and MCP answer with",
6390 description: "What `GET /api/v1/intents` returns and the `majordomus_intents` tool answers: the count, the tally by stage, and every intent with its milestones and criteria.",
6391 argv: &["intent", "list", "--format", "json"],
6392 setup: &[],
6393 expect: Expect::Json(&["/count", "/stages", "/intents/0/stage", "/intents/0/satisfaction"]),
6394 },
6395 ],
6396 },
6397 CommandExamples {
6398 command: "intent show",
6399 examples: &[ExampleDoc {
6400 id: "intent-show",
6401 title: "One intent, with each milestone and criterion derived",
6402 description: "The statement and invariants as authored, each milestone with its derived status, and each criterion with the state of its evidence and the command that reproduces it.",
6403 argv: &["intent", "show", "fixture-intent"],
6404 setup: &[],
6405 expect: Expect::StdoutContains(&["fixture-intent", "stage"]),
6406 }],
6407 },
6408 CommandExamples {
6409 command: "intent validate",
6410 examples: &[ExampleDoc {
6411 id: "intent-validate",
6412 title: "Check the intents before anything relies on them",
6413 description: "An intent naming no milestone, a milestone or evidence reference that resolves to nothing, governance that names nothing: each a failure, and exit 10. A milestone no intent serves is a warning.",
6414 argv: &["intent", "validate"],
6415 setup: &[],
6416 expect: Expect::StdoutContains(&["intent(s)", "valid"]),
6417 }],
6418 },
6419 CommandExamples {
6420 command: "intent coverage",
6421 examples: &[
6422 ExampleDoc {
6423 id: "intent-coverage",
6424 title: "Which work carries which criterion, and why every issue exists",
6425 description: "Every criterion of every live intent with the issues that serve it and how strongly — covered, weakly covered, observed by the recorded gap, or uncovered — and every issue with the reason it exists: the criteria it serves, or maintenance under a milestone no intent names.",
6426 argv: &["intent", "coverage"],
6427 setup: &[],
6428 expect: Expect::StdoutContains(&["CRITERION", "criterion(s)"]),
6429 },
6430 ExampleDoc {
6431 id: "intent-coverage-json",
6432 title: "The same, as the shape the API and MCP answer with",
6433 description: "What `GET /api/v1/intents/coverage` returns and the `majordomus_intent_coverage` tool answers: each criterion with its strength and the issues serving it, and each issue with its origin.",
6434 argv: &["intent", "coverage", "--format", "json"],
6435 setup: &[],
6436 expect: Expect::Json(&["/criteria/0/strength", "/criteria/0/issues", "/issues/0/origin"]),
6437 },
6438 ],
6439 },
6440 CommandExamples {
6441 command: "intent preflight",
6442 examples: &[ExampleDoc {
6443 id: "intent-preflight",
6444 title: "Which intent the work on an issue serves, or why it may not proceed",
6445 description: "The issue followed through the criteria it declares it serves to the intent each belongs to, with what that intent asks of the worker: its statement, the served criteria and their evidence, invariants, non-goals, governance, critique and gap. A broken link, or an intent whose plan was never critiqued or has a blocking finding open, is a refusal naming its cause, and exit 10; the example fixture's intent has no critique, so this is that refusal. Work under milestones no intent names is maintenance, and exits 0.",
6446 argv: &["intent", "preflight", "--issue", "I0001"],
6447 setup: &[],
6448 expect: Expect::ExitCode(10),
6449 }],
6450 },
6451 CommandExamples {
6452 command: "intent binding",
6453 examples: &[ExampleDoc {
6454 id: "intent-binding",
6455 title: "What a task is bound to before it starts",
6456 description: "What `majordomus start --issue` asks: the issue resolved to the intent and the criteria it serves, with what the intent asks of the worker and the two pins a handover carries. The example fixture's intent has no critique, so the binding is refused naming that cause, and exits 10; a bound issue answers `bound`, an issue under a milestone no intent names `maintenance`, and `--exempt <class> --because <reason>` answers `exempt` when the policy declares the class.",
6457 argv: &["intent", "binding", "--issue", "I0001"],
6458 setup: &[],
6459 expect: Expect::ExitCode(10),
6460 }],
6461 },
6462 CommandExamples {
6463 command: "intent realization",
6464 examples: &[
6465 ExampleDoc {
6466 id: "intent-realization",
6467 title: "Which work realises which intent, and what each still lacks",
6468 description: "Every intent with its unmet criteria and the work realising it, then every task, session record and peer claim with its strongest link — declared, observed, derived or inferred — or the first missing link. Exit 10 when an intent whose milestones are all DONE is contradicted by its evidence.",
6469 argv: &["intent", "realization"],
6470 setup: &[],
6471 expect: Expect::StdoutContains(&["fixture-intent", "unit(s) of work"]),
6472 },
6473 ExampleDoc {
6474 id: "intent-realization-json",
6475 title: "The same, as the shape the API and MCP answer with",
6476 description: "What `GET /api/v1/intents/realization` returns and the `majordomus_intent_realization` tool answers: each intent's unmet criteria, work and providers, and each unit of work with its links.",
6477 argv: &["intent", "realization", "--format", "json"],
6478 setup: &[],
6479 expect: Expect::Json(&["/intents/0/stage", "/intents/0/unmet", "/work", "/orphans"]),
6480 },
6481 ],
6482 },
6483 CommandExamples {
6484 command: "intent explain",
6485 examples: &[ExampleDoc {
6486 id: "intent-explain",
6487 title: "Why an intent stands where it stands",
6488 description: "A sentence for the stage naming each milestone's derived status, one per criterion naming its evidence state and coverage, and one for the work realising it — all derived, none stored.",
6489 argv: &["intent", "explain", "fixture-intent"],
6490 setup: &[],
6491 expect: Expect::StdoutContains(&["fixture-intent", "the-case-passes"]),
6492 }],
6493 },
6494 CommandExamples {
6495 command: "intent propose",
6496 examples: &[ExampleDoc {
6497 id: "intent-propose",
6498 title: "Propose an intent: what must become true",
6499 description: "Writes a new record under `.ai/repo/project/intents/` holding the statement and nothing else yet (ADR 0144): no milestone, criterion or invariant. Its stage derives as `declared`, `intent validate` reports the two absences as warnings, and no work can serve it until it is planned. `--title` and `--id` default to the statement's first line and that line's slug; an identity that exists is refused, never overwritten.",
6500 argv: &["intent", "propose", "--statement", "Every page answers within 100 ms when warm"],
6501 setup: &[],
6502 expect: Expect::StdoutContains(&[
6503 "proposed every-page-answers-within-100-ms-when-warm",
6504 ".ai/repo/project/intents/every-page-answers-within-100-ms-when-warm.yaml",
6505 ]),
6506 }],
6507 },
6508 CommandExamples {
6509 command: "serve status",
6510 examples: &[ExampleDoc {
6511 id: "serve-status",
6512 title: "Where this checkout's server stands, and every server of the repository",
6513 description: "The standing of this checkout's server measured against what this executable would serve, the lease it holds, and every checkout git registers for the repository with its own server. Asked of the running server when there is one, so that the answer includes the lease that process holds; answered locally otherwise.",
6514 argv: &["serve", "status"],
6515 setup: &[],
6516 expect: Expect::StdoutContains(&["standing"]),
6517 }],
6518 },
6519 CommandExamples {
6520 command: "serve ensure",
6521 examples: &[ExampleDoc {
6522 id: "serve-ensure-idle",
6523 title: "Make sure a server serves this checkout, and let it end when idle",
6524 description: "Starts a server as a process of its own when none answers, waits until it is ready, and prints one line: the standing, the address, the pid. Run again, it finds the server ready and starts nothing. `--idle` is how long the started server outlives its last peer; one second here, so that the example leaves nothing behind.",
6525 argv: &["serve", "ensure", "--idle", "1", "--wait", "30"],
6526 setup: &[],
6527 expect: Expect::StdoutContains(&["ready"]),
6528 }],
6529 },
6530 CommandExamples {
6531 command: "serve stop",
6532 examples: &[ExampleDoc {
6533 id: "serve-stop-nothing",
6534 title: "Stop this checkout's server, when there is one",
6535 description: "Signals the server this checkout's lease names, when it answers for this checkout, and waits for that server's lease to go — the one it read, by its token, so a second process taking the checkout over in the same instant is reported rather than mistaken for a server that would not stop. A checkout with no lease has nothing to stop, and says so.",
6536 argv: &["serve", "stop"],
6537 setup: &[],
6538 expect: Expect::StdoutContains(&["nothing to stop"]),
6539 }],
6540 },
6541 CommandExamples {
6542 command: "serve",
6543 examples: &[ExampleDoc {
6544 id: "serve-ephemeral-port",
6545 title: "Serve the same capabilities over HTTP on a free port",
6546 description: "Port 0 asks the operating system for a free port; the address is logged on stderr. `/` is the home page, generated from the surfaces this process resolved; the document at /openapi.json is the same one `majordomus generate` commits; /swagger is the Swagger UI over it; /docs/ is this repository's documentation when it has been built for that mount.",
6547 argv: &["serve", "--port", "0"],
6548 setup: &[],
6549 expect: Expect::HttpReady("/openapi.json"),
6550 }],
6551 },
6552 CommandExamples {
6553 command: "capabilities list",
6554 examples: &[
6555 ExampleDoc {
6556 id: "capabilities-list-cli",
6557 title: "Which capabilities the command line itself dispatches to",
6558 description: "One line per capability exposed through the `cli` projection, with the projections of each. The registry answers this; no list of capabilities is written in the command line's own declaration.",
6559 argv: &["capabilities", "list", "--exposure", "cli"],
6560 setup: &[],
6561 expect: Expect::StdoutContains(&["capabilities.list", "capabilities.describe"]),
6562 },
6563 ExampleDoc {
6564 id: "capabilities-list-json",
6565 title: "Every capability as one JSON document",
6566 description: "The whole registry for a script: each capability with its kind, its provenance and every projection it has.",
6567 argv: &["capabilities", "list", "--format", "json"],
6568 setup: &[],
6569 expect: Expect::Json(&["/capabilities"]),
6570 },
6571 ],
6572 },
6573 CommandExamples {
6574 command: "capabilities describe",
6575 examples: &[ExampleDoc {
6576 id: "capabilities-describe-objects-get",
6577 title: "One capability in full, by its canonical id",
6578 description: "Its kind, its input and output schemas, where it was composed, and every projection of it: the MCP tool or resource, the HTTP route, the CLI path.",
6579 argv: &["capabilities", "describe", "objects.get"],
6580 setup: &[],
6581 expect: Expect::StdoutContains(&["objects.get", "GET /api/v1/object"]),
6582 }],
6583 },
6584 CommandExamples {
6585 command: "capabilities schema",
6586 examples: &[ExampleDoc {
6587 id: "capabilities-schema-output",
6588 title: "The canonical output schema of a capability",
6589 description: "The JSON Schema the MCP and OpenAPI projections are derived from; `--side input` prints the schema of what the capability accepts.",
6590 argv: &["capabilities", "schema", "objects.get", "--side", "output"],
6591 setup: &[],
6592 expect: Expect::Json(&["/title"]),
6593 }],
6594 },
6595 CommandExamples {
6596 command: "capabilities projections",
6597 examples: &[
6598 ExampleDoc {
6599 id: "capabilities-projections-unmet",
6600 title: "Every exposure a capability claims that its surface does not answer",
6601 description: "`rows: 0` is the closure `project.interfaces-are-projections` asks for: every declared command line, route and tool is answered by the surface that carries it. The commands no capability claims are reported beside it, as the measure of how much of the command line is still hand-written.",
6602 argv: &["capabilities", "projections", "--unmet"],
6603 setup: &[],
6604 expect: Expect::Success,
6605 },
6606 ExampleDoc {
6607 id: "capabilities-projections-module",
6608 title: "Where one module's capabilities appear",
6609 description: "A row per capability with the command line, HTTP route and MCP tool it reaches, so a capability that exists but is reachable from nowhere is visible as one.",
6610 argv: &["capabilities", "projections", "--module", "worktree"],
6611 setup: &[],
6612 expect: Expect::StdoutContains(&["worktree.topology", "majordomus worktree topology"]),
6613 },
6614 ],
6615 },
6616 CommandExamples {
6617 command: "capabilities validate",
6618 examples: &[ExampleDoc {
6619 id: "capabilities-validate",
6620 title: "Prove the registry and every projection of it",
6621 description: "Builds the registry, the MCP and HTTP surfaces, the OpenAPI document, the command line's documentation and the benchmark coverage, and names every failure. Exit 10 when anything is unmet.",
6622 argv: &["capabilities", "validate"],
6623 setup: &[],
6624 expect: Expect::StdoutContains(&["validate: 0 failure(s)", "OK cli"]),
6625 }],
6626 },
6627 CommandExamples {
6628 command: "generate",
6629 examples: &[
6630 ExampleDoc {
6631 id: "generate-all",
6632 title: "Write every committed projection",
6633 description: "The OpenAPI document, the capability reference, the command-line reference and its JSON, the registry manifest, the benchmark matrix, the shell tool's allow-lists, the provider bootstraps and the site's registry dataset — all from the one registry and the one clap declaration.",
6634 argv: &["generate"],
6635 setup: &[],
6636 expect: Expect::Success,
6637 },
6638 ExampleDoc {
6639 id: "generate-check",
6640 title: "Refuse a tree whose projections are stale",
6641 description: "Writes nothing and compares instead: exit 0 when every committed projection is what the sources produce, exit 10 with each stale file named. This is the form CI runs.",
6642 argv: &["generate", "--check"],
6643 setup: &[&["generate"]],
6644 expect: Expect::Success,
6645 },
6646 ExampleDoc {
6647 id: "generate-one-target",
6648 title: "One target only",
6649 description: "Each target can be written on its own while a change is iterated on; `majordomus generate` with no target writes all of them.",
6650 argv: &["generate", "openapi"],
6651 setup: &[],
6652 expect: Expect::Success,
6653 },
6654 ExampleDoc {
6655 id: "generate-site-check",
6656 title: "Check one target without writing it",
6657 description: "`--check` composes with a target: here only the registry dataset the site renders is compared with what the sources produce, exit 10 naming it when it is stale.",
6658 argv: &["generate", "site", "--check"],
6659 setup: &[&["generate", "site"]],
6660 expect: Expect::Success,
6661 },
6662 ],
6663 },
6664 CommandExamples {
6665 command: "bench",
6666 examples: &[ExampleDoc {
6667 id: "bench-direct-quick",
6668 title: "Time the capabilities in process",
6669 description: "The quick profile takes few samples, and `--transport direct` measures the executor without spawning a server. Nothing is written under .ai/local/ with `--no-write`.",
6670 argv: &[
6671 "bench",
6672 "--transport",
6673 "direct",
6674 "--profile",
6675 "quick",
6676 "--no-write",
6677 "--format",
6678 "json",
6679 ],
6680 setup: &[],
6681 expect: Expect::Json(&["/results", "/profile"]),
6682 }],
6683 },
6684 CommandExamples {
6685 command: "bench coverage",
6686 examples: &[
6687 ExampleDoc {
6688 id: "bench-coverage-json",
6689 title: "Every required benchmark target and whether it is covered",
6690 description: "The denominator is generated from the registry: every executable capability, on every transport it is exposed on, plus the transports' own operations.",
6691 argv: &["bench", "coverage", "--format", "json"],
6692 setup: &[],
6693 expect: Expect::Json(&["/lines", "/tallies"]),
6694 },
6695 ExampleDoc {
6696 id: "bench-coverage-check",
6697 title: "Fail when a target is missing",
6698 description: "Exit 10 when any required target is uncovered or waived, so a capability that nothing times cannot be merged.",
6699 argv: &["bench", "coverage", "--check"],
6700 setup: &[],
6701 expect: Expect::Success,
6702 },
6703 ],
6704 },
6705 CommandExamples {
6706 command: "bench baseline update",
6707 examples: &[ExampleDoc {
6708 id: "bench-baseline-update-quick",
6709 title: "Record this platform's accepted baseline",
6710 description: "Runs the benchmarks and writes the result under .ai/repo/benchmarks/rust/ as a tracked, reviewable file. The full profile is the default; the quick profile is for trying the path out. A dirty work tree is refused unless --allow-dirty says otherwise.",
6711 argv: &[
6712 "bench",
6713 "baseline",
6714 "update",
6715 "--profile",
6716 "quick",
6717 "--allow-dirty",
6718 ],
6719 setup: &[],
6720 expect: Expect::Success,
6721 }],
6722 },
6723 CommandExamples {
6724 command: "scope",
6725 examples: &[
6726 ExampleDoc {
6727 id: "scope-declaration",
6728 title: "What a worker reads of this repository",
6729 description: "With no path, the declaration itself and the tally: how many tracked files are in the scope and how many are out.",
6730 argv: &["scope"],
6731 setup: &[],
6732 expect: Expect::Success,
6733 },
6734 ExampleDoc {
6735 id: "scope-paths-json",
6736 title: "Judge paths, and say which rule decided",
6737 description: "For each path: in or out, and the rule that decided it. `--check` exits 10 when any path given is out, which is how a hook refuses to read one.",
6738 argv: &["scope", "docs/CLI.md", "--format", "json"],
6739 setup: &[],
6740 expect: Expect::Json(&["/0/verdict", "/0/rule"]),
6741 },
6742 ],
6743 },
6744 CommandExamples {
6745 command: "commands",
6746 examples: &[ExampleDoc {
6747 id: "commands-list",
6748 title: "Every command this repository offers",
6749 description: "The command graph, composed from the three declarations that already exist: the clap tree of this executable, the shipped command registry of the shell tool, and the recipes the workflow runner describes. One line per command, with the program that runs it and what running it changes.",
6750 argv: &["commands"],
6751 setup: &[],
6752 expect: Expect::StdoutContains(&["commands", "executable", "read-only"]),
6753 }],
6754 },
6755 CommandExamples {
6756 command: "commands list",
6757 examples: &[ExampleDoc {
6758 id: "commands-list-filtered",
6759 title: "Only what reads",
6760 description: "The filters are the graph's own vocabulary rather than a search over text: `--effect read-only` is every command that changes nothing anywhere, which is the same predicate the exposure policy uses to decide what a machine surface may call.",
6761 argv: &["commands", "list", "--effect", "read-only"],
6762 setup: &[],
6763 expect: Expect::StdoutContains(&["read-only"]),
6764 }],
6765 },
6766 CommandExamples {
6767 command: "commands show",
6768 examples: &[ExampleDoc {
6769 id: "commands-show",
6770 title: "One command, and every surface that carries it",
6771 description: "The arguments with the source of each one's values, the effect, and the projections: the command line, the workflow recipe, the MCP tool, the HTTP route, the Cockpit and the page. A surface that withholds it says why.",
6772 argv: &["commands", "show", "executable.worktree.status"],
6773 setup: &[],
6774 expect: Expect::StdoutContains(&["executable.worktree.status", "projections"]),
6775 }],
6776 },
6777 CommandExamples {
6778 command: "commands explain",
6779 examples: &[ExampleDoc {
6780 id: "commands-explain",
6781 title: "Why a command appears where it does",
6782 description: "The same command with its provenance: the file that declares it, the reader that found it, the capability behind it when there is one, what it requires, and the file the exposure policy lives in. Nothing about a command's placement is a mystery a grep has to solve.",
6783 argv: &["commands", "explain", "executable.serve"],
6784 setup: &[],
6785 expect: Expect::StdoutContains(&["declared in", "policy"]),
6786 }],
6787 },
6788 CommandExamples {
6789 command: "commands graph",
6790 examples: &[ExampleDoc {
6791 id: "commands-graph-json",
6792 title: "The whole graph as one document",
6793 description: "Deterministic and fingerprinted: two builds over one tree produce the same bytes, which is what lets the workflow bridge, the completion index and the Cockpit all key on the fingerprint instead of regenerating.",
6794 argv: &["commands", "graph", "--format", "json"],
6795 setup: &[],
6796 expect: Expect::Json(&["/schema", "/fingerprint", "/commands"]),
6797 }],
6798 },
6799 CommandExamples {
6800 command: "commands bridge",
6801 examples: &[ExampleDoc {
6802 id: "commands-bridge",
6803 title: "The workflow runner's recipes, derived",
6804 description: "Every command of both programs, written as a recipe that runs the canonical program with the caller's own arguments. It goes under .ai/local/cache/, which no commit carries, and it is rewritten only when the graph's fingerprint changes.",
6805 argv: &["commands", "bridge"],
6806 setup: &[],
6807 expect: Expect::StdoutContains(&["bridge", "recipe"]),
6808 }],
6809 },
6810 CommandExamples {
6811 command: "completion",
6812 examples: &[ExampleDoc {
6813 id: "completion-default",
6814 title: "The integration a person installs once",
6815 description: "With no subcommand, the shell integration for zsh. It contains no command, no flag and no identifier: every candidate comes from a query against the command graph of the repository the shell is in, so one integration serves every checkout and never goes stale.",
6816 argv: &["completion"],
6817 setup: &[],
6818 expect: Expect::StdoutContains(&["completion query", "compdef"]),
6819 }],
6820 },
6821 CommandExamples {
6822 command: "completion init",
6823 examples: &[ExampleDoc {
6824 id: "completion-init-bash",
6825 title: "The same, for bash",
6826 description: "A different shell's protocol, the same question. Both adapters read the words being completed, find the cursor, ask this executable and print what comes back.",
6827 argv: &["completion", "init", "--shell", "bash"],
6828 setup: &[],
6829 expect: Expect::StdoutContains(&["completion query", "complete -F"]),
6830 }],
6831 },
6832 CommandExamples {
6833 command: "completion query",
6834 examples: &[ExampleDoc {
6835 id: "completion-query",
6836 title: "What a shell asks on every TAB",
6837 description: "The words of the command line and the position of the cursor; back come the candidates with their descriptions. The same call answers the workflow runner's completion with `--surface workflow`, resolving the recipe name to the command it bridges and then completing that command's own arguments.",
6838 argv: &["completion", "query", "--surface", "cli", "--", "majordomus", "work"],
6839 setup: &[],
6840 expect: Expect::StdoutContains(&["worktree"]),
6841 }],
6842 },
6843 CommandExamples {
6844 command: "quality report",
6845 examples: &[
6846 ExampleDoc {
6847 id: "quality-summary",
6848 title: "Where the crate's public surface stands",
6849 description: "The counts alone: how much of the exported surface is documented and exampled, how many modules something exercises, and how the canonical operations stand against the command line, HTTP, OpenAPI and MCP. Exits 10 when any finding stands outside the recorded baseline.",
6850 argv: &["quality", "report", "--summary"],
6851 setup: &[],
6852 expect: Expect::Success,
6856 },
6857 ExampleDoc {
6858 id: "quality-code-json",
6859 title: "One kind of finding, with the rule and the remedy",
6860 description: "Filtered to one violation code. Every finding carries the rule that requires it, where it is, why it matters and what to do — which is what lets a person and an agent act on the same report.",
6861 argv: &[
6862 "quality",
6863 "report",
6864 "--code",
6865 "RUST_MODULE_MISSING_EXAMPLE",
6866 "--format",
6867 "json",
6868 ],
6869 setup: &[],
6870 expect: Expect::Json(&["/measured", "/passes", "/report/schema"]),
6871 },
6872 ],
6873 },
6874 CommandExamples {
6875 command: "quality rustdoc",
6876 examples: &[
6877 ExampleDoc {
6878 id: "quality-rustdoc",
6879 title: "Whether the crate's rustdoc tree is complete, current and sound",
6880 description: "The rustdoc surface's tree judged against the crate's own inventory: every exported item's page at its route, no page without an item, built from HEAD, the index and its assets present, every relative link resolved, nothing naming the machine or shaped like a credential. Exits 0 clean, 10 with findings, and 12 when there is nothing to judge — as here, in a repository that carries no Rust crate, or wherever the producer (scripts/rust-check --doc) has not run. A check that cannot see its subject says so; it never reports clean.",
6881 argv: &["quality", "rustdoc"],
6882 setup: &[],
6883 expect: Expect::ExitCode(12),
6884 },
6885 ExampleDoc {
6886 id: "quality-rustdoc-tree-json",
6887 title: "Another copy of the tree, judged the same way",
6888 description: "A directory named on the command line — the tree scripts/site-build composed into the site — judged by the same judgement, as the document every transport answers with: the verdict, the counts, every exported module with its page, and one typed finding per defect. Only a person at their own terminal names a directory; over HTTP and MCP the subject is always the surface's artifact.",
6889 argv: &["quality", "rustdoc", "--tree", "site/public/rustdoc", "--format", "json"],
6890 setup: &[],
6891 expect: Expect::ExitCode(12),
6892 },
6893 ],
6894 },
6895 CommandExamples {
6896 command: "economics summary",
6897 examples: &[
6898 ExampleDoc {
6899 id: "economics-summary",
6900 title: "What the evidence allows to be said about tokens",
6901 description: "Every metric with its measurement class, sample size and interval, the state of each suite's evidence, and the one statement the publication rule allows. In a repository that declares no benchmark methodology — which is where the examples run — the statement is that no verified total-token-savings claim is available, and no number is printed.",
6902 argv: &["economics", "summary"],
6903 setup: &[],
6904 expect: Expect::StdoutContains(&["No verified total-token-savings claim"]),
6905 },
6906 ExampleDoc {
6907 id: "economics-summary-json",
6908 title: "The same answer as the API and MCP give it",
6909 description: "The typed summary: the verdict, the metrics, the pairs and the segments, exactly as GET /api/v1/economics and the majordomus_economics tool return them.",
6910 argv: &["economics", "summary", "--format", "json"],
6911 setup: &[],
6912 expect: Expect::Json(&["/present", "/verdict/statement", "/metrics"]),
6913 },
6914 ],
6915 },
6916 CommandExamples {
6917 command: "economics explain",
6918 examples: &[ExampleDoc {
6919 id: "economics-explain",
6920 title: "Everything one metric rests on",
6921 description: "The metric's formula, class, pairs, runs, exclusions and the commands that reproduce it. In a repository that declares no benchmark methodology — which is where the examples run — there is no metric: any id is answered with the statement why, exit 0 and no number. A metric id a declared methodology does not have is refused with the list of those that do (exit 12).",
6922 argv: &["economics", "explain", "effective_token_reduction"],
6923 setup: &[],
6924 expect: Expect::StdoutContains(&["no benchmark methodology is declared"]),
6925 }],
6926 },
6927 CommandExamples {
6928 command: "economics runs",
6929 examples: &[ExampleDoc {
6930 id: "economics-runs-json",
6931 title: "The raw facts behind every number",
6932 description: "Every recorded run with its gate verdicts and the totals derived from its provider usage. None where nothing was run.",
6933 argv: &["economics", "runs", "--format", "json"],
6934 setup: &[],
6935 expect: Expect::Json(&["/count", "/runs"]),
6936 }],
6937 },
6938 CommandExamples {
6939 command: "economics check",
6940 examples: &[ExampleDoc {
6941 id: "economics-check",
6942 title: "Refuse a savings claim nothing measured",
6943 description: "Scans the hand-written prose and claim sentences for a quantity next to the economics vocabulary, and checks every claim bound to a metric. Exits 10 naming each finding; exits 0 here, where nothing claims anything.",
6944 argv: &["economics", "check"],
6945 setup: &[],
6946 expect: Expect::StdoutContains(&["economics check:", "0 finding(s)"]),
6947 }],
6948 },
6949 CommandExamples {
6950 command: "economics measure",
6951 examples: &[ExampleDoc {
6952 id: "economics-measure-dry-run",
6953 title: "Count what the context compiler selects",
6954 description: "Runs the deterministic context suite: no model is called; every seed's candidates and selection are counted with a pinned tokenizer. Refused with exit 12 where no methodology is declared.",
6955 argv: &["economics", "measure", "--dry-run"],
6956 setup: &[],
6957 expect: Expect::ExitCode(12),
6958 }],
6959 },
6960 CommandExamples {
6961 command: "economics run",
6962 examples: &[ExampleDoc {
6963 id: "economics-run-dry-run",
6964 title: "Prepare a live suite without spending anything",
6965 description: "Builds every control and treatment workspace and prints the harness command each session would run; nothing is sent to a provider. Refused with exit 12 where no methodology is declared.",
6966 argv: &["economics", "run", "--suite", "pilot", "--dry-run"],
6967 setup: &[],
6968 expect: Expect::ExitCode(12),
6969 }],
6970 },
6971 CommandExamples {
6972 command: "economics references",
6973 examples: &[ExampleDoc {
6974 id: "economics-references",
6975 title: "Prove every task can be failed and can be passed",
6976 description: "Applies each task's reference solution to its fixture: the hidden tests must fail on the starting state and pass on the reference. Refused with exit 12 where no methodology is declared.",
6977 argv: &["economics", "references"],
6978 setup: &[],
6979 expect: Expect::ExitCode(12),
6980 }],
6981 },
6982 CommandExamples {
6983 command: "devcontext compile",
6984 examples: &[
6985 ExampleDoc {
6986 id: "devcontext-compile-issue",
6987 title: "The context a session working on one issue should be given",
6988 description: "The issue is the seed. Its milestone follows along the `belongs_to` edge of the composed graph, the code and the cases under the scope it declares follow from the paths, and the policy and the scope are governance every session is held to. Every selected line names the selector that reached it and why; everything left out is listed with the reason.",
6989 argv: &["devcontext", "compile", "--issue", "I0001"],
6990 setup: &[],
6991 expect: Expect::StdoutContains(&["SELECTED", "majordomus://issue/I0001", "EXCLUDED"]),
6992 },
6993 ExampleDoc {
6994 id: "devcontext-compile-json",
6995 title: "The same, as the structure every other surface answers with",
6996 description: "The canonical form: `GET /api/v1/devcontext` and the `majordomus_devcontext` tool return this document. Entries keep their canonical identifier, the index's provenance, every discovery path with its confidence, and the cost in estimated tokens; nothing is flattened to prose.",
6997 argv: &["devcontext", "compile", "--issue", "I0001", "--format", "json"],
6998 setup: &[],
6999 expect: Expect::Json(&["/selected/0/uri", "/selected/0/discovered_by/0/reason", "/budget/limit_tokens", "/fingerprint"]),
7000 },
7001 ],
7002 },
7003 CommandExamples {
7004 command: "devcontext explain",
7005 examples: &[ExampleDoc {
7006 id: "devcontext-explain-seed",
7007 title: "Why one thing is in the context",
7008 description: "The identifier is judged under the same request `compile` takes: selected, excluded with the reason, folded into another identifier, held by the index and never reached, or unknown.",
7009 argv: &["devcontext", "explain", "majordomus://issue/I0001", "--issue", "I0001"],
7010 setup: &[],
7011 expect: Expect::StdoutContains(&["selected", "majordomus://issue/I0001"]),
7012 }],
7013 },
7014 CommandExamples {
7015 command: "devcontext policy",
7016 examples: &[ExampleDoc {
7017 id: "devcontext-policy",
7018 title: "The compiler's own rules",
7019 description: "The tiers in the order the budget spends in, every edge kind the composed graph declares with the weight it is followed by or the reason it is refused, and which selectors infer rather than read.",
7020 argv: &["devcontext", "policy"],
7021 setup: &[],
7022 expect: Expect::StdoutContains(&["TIER", "is_a", "REFUSED"]),
7023 }],
7024 },
7025 CommandExamples {
7026 command: "offload hosts",
7027 examples: &[ExampleDoc {
7028 id: "offload-hosts-json",
7029 title: "The declared hosts, or the answer that there are none",
7030 description: "Reads the repository's derive-offload declaration (.ai/repo/offload/*.yaml) and prints it with every default filled in: the hosts in tie-break order, each one's free-space minimum and ssh identity file, the queue's paths and the layout on a host. No host is contacted. This fixture declares none, which is an answer, not an error: `declared` is false and the declaration is null.",
7031 argv: &["offload", "hosts", "--format", "json"],
7032 setup: &[],
7033 expect: Expect::Json(&["/declared", "/declaration"]),
7034 }],
7035 },
7036 CommandExamples {
7037 command: "offload probe",
7038 examples: &[ExampleDoc {
7039 id: "offload-probe-undeclared",
7040 title: "No declared host, no probe",
7041 description: "Measures every declared host over ssh — free space under its home, derives running or waiting in its queue — and names the one a derive would take: the eligible host with the fewest, ties to the one declared first. A repository that declares no host has nothing to measure, and the probe refuses with 12 rather than reporting an empty success.",
7042 argv: &["offload", "probe"],
7043 setup: &[],
7044 expect: Expect::ExitCode(12),
7045 }],
7046 },
7047 CommandExamples {
7048 command: "offload derive",
7049 examples: &[ExampleDoc {
7050 id: "offload-derive-undeclared",
7051 title: "A derive with nowhere to go is refused before anything travels",
7052 description: "Sends the worktree as it stands to a declared host as a git bundle, waits its turn in the host's FIFO queue, derives in a build directory of its own and stages the files the derive changed; nothing is committed or pushed. With no host declared it refuses with 12 before it reads the worktree, contacts anything or writes a ref.",
7053 argv: &["offload", "derive", "."],
7054 setup: &[],
7055 expect: Expect::ExitCode(12),
7056 }],
7057 },
7058 CommandExamples {
7059 command: "guard hook",
7060 examples: &[ExampleDoc {
7061 id: "guard-hook",
7062 title: "Judge the edit a provider's pre-tool payload names",
7063 description: "What a provider's pre-tool hook runs before an edit: the payload arrives on stdin, and the command exits 2 with the reason and the remedy when no claim covers the path it names, 0 otherwise. Here stdin is empty, so it names no path, and the command lets the tool run.",
7064 argv: &["guard", "hook", "--provider", "claude-code"],
7065 setup: &[],
7066 expect: Expect::Success,
7067 }],
7068 },
7069 CommandExamples {
7070 command: "mesh status",
7071 examples: &[ExampleDoc {
7072 id: "mesh-status",
7073 title: "Whether this checkout's server runs a mesh",
7074 description: "The mesh lives inside the shared server, so the command asks the running server for `mesh.status` and renders it. No server, or no mesh declaration, is an answer with its reason — never an error: the default posture is that nothing leaves the machine until a declaration says otherwise.",
7075 argv: &["mesh", "status"],
7076 setup: &[],
7077 expect: Expect::StdoutContains(&["mesh"]),
7078 }],
7079 },
7080 CommandExamples {
7081 command: "mesh nodes",
7082 examples: &[ExampleDoc {
7083 id: "mesh-nodes",
7084 title: "The nodes the running server has observed",
7085 description: "One row per node, deduplicated by node identity across every discovery source, in node-id order: trust, presence, endpoints and where each observation came from. The registry lives in the server's memory; without a running server there are no nodes to list, and the command says so.",
7086 argv: &["mesh", "nodes"],
7087 setup: &[],
7088 expect: Expect::StdoutContains(&["mesh"]),
7089 }],
7090 },
7091 CommandExamples {
7092 command: "mesh identity",
7093 examples: &[ExampleDoc {
7094 id: "mesh-identity",
7095 title: "This machine's node identity, public half only",
7096 description: "The node id is a digest of the machine's Ed25519 public key, kept under the user's state directory — never inside a repository, and the signing key appears in no output. Absent is an answer: the identity is created when a mesh first activates.",
7097 argv: &["mesh", "identity"],
7098 setup: &[],
7099 expect: Expect::StdoutContains(&["present"]),
7100 }],
7101 },
7102 CommandExamples {
7103 command: "mesh doctor",
7104 examples: &[ExampleDoc {
7105 id: "mesh-doctor",
7106 title: "Every mesh prerequisite, and the server's verdict on the declaration",
7107 description: "Deterministic checks in a fixed order — the declaration parses, the identity loads, a UDP socket binds, the multicast group joins, broadcast enables, and the protocol signs, encodes, parses and verifies in memory — then `runtime`: asked of this checkout's running server when one serves it, whether an enabled declaration actually activated the mesh. With no server, as here, the report is this process's and `runtime` says nothing was decided. Every check holds here, so the command exits 0; a failed check is a row that says why, and exits 10.",
7108 argv: &["mesh", "doctor"],
7109 setup: &[],
7110 expect: Expect::StdoutContains(&["protocol"]),
7111 }],
7112 },
7113 CommandExamples {
7114 command: "mesh firewall",
7115 examples: &[ExampleDoc {
7116 id: "mesh-firewall",
7117 title: "What the host firewall must admit for the declared mesh, and whether it does",
7118 description: "The admissions derived from the declaration and this machine's addresses — the multicast group's port, the hub ports whose address is this machine's, the server's port beyond loopback — the firewall front this host runs, the commands that admit them there, the firewall's own word about them, and what the kernel logged it dropping toward those ports in the last five minutes. Here, with no declaration, nothing is needed and the report says so; a rule observed missing or a logged drop exits 10.",
7119 argv: &["mesh", "firewall"],
7120 setup: &[],
7121 expect: Expect::StdoutContains(&["backend", "verdict"]),
7122 }],
7123 },
7124 CommandExamples {
7125 command: "mesh firewall apply",
7126 examples: &[ExampleDoc {
7127 id: "mesh-firewall-apply",
7128 title: "Admit the mesh through the host firewall, as root",
7129 description: "Runs the commands `mesh firewall` renders — one allow per rule and source network on ufw or nftables, the executable admitted on the macOS application firewall — and asks the firewall again, so the verdict is its own. It refuses, running nothing, without root or without a backend, and exits 10, as here, where nothing is declared and the example does not run as root.",
7130 argv: &["mesh", "firewall", "apply"],
7131 setup: &[],
7132 expect: Expect::ExitCode(10),
7133 }],
7134 },
7135 CommandExamples {
7136 command: "mesh peers",
7137 examples: &[ExampleDoc {
7138 id: "mesh-peers",
7139 title: "Who cooperates, machine by machine",
7140 description: "Machines, runtimes, sessions and claims, from this checkout's running server. With no server, or with cooperation off, the answer says so and why — the mesh lives in the server's memory.",
7141 argv: &["mesh", "peers"],
7142 setup: &[],
7143 expect: Expect::StdoutContains(&["cooperation inactive"]),
7144 }],
7145 },
7146 CommandExamples {
7147 command: "mesh peer",
7148 examples: &[ExampleDoc {
7149 id: "mesh-peer",
7150 title: "One runtime, by its key",
7151 description: "A runtime's machine, liveness, link, sessions and claims. A runtime the running server does not know is `not found`; with no server there is nobody to ask, and the answer says that rather than reporting an absence it never measured.",
7152 argv: &["mesh", "peer", "00000000000000000000000000000000-0000000000000000"],
7153 setup: &[],
7154 expect: Expect::StdoutContains(&["cooperation inactive"]),
7155 }],
7156 },
7157 CommandExamples {
7158 command: "mesh state",
7159 examples: &[ExampleDoc {
7160 id: "mesh-state",
7161 title: "The state every linked runtime converges on",
7162 description: "Sessions, claims with their standing, handovers, reviews and the digest two runtimes compare — or, with no running server, why there is none.",
7163 argv: &["mesh", "state"],
7164 setup: &[],
7165 expect: Expect::StdoutContains(&["cooperation inactive"]),
7166 }, ExampleDoc {
7167 id: "mesh-state-live-claims",
7168 title: "Every claim still held",
7169 description: "The whole state with only the claims still held, as docs/MESH.md lists it — or, with no running server, why there is none.",
7170 argv: &["mesh", "state", "--full", "--live-claims"],
7171 setup: &[],
7172 expect: Expect::StdoutContains(&["cooperation inactive"]),
7173 }],
7174 },
7175 CommandExamples {
7176 command: "monitor",
7177 examples: &[
7178 ExampleDoc {
7179 id: "monitor-page",
7180 title: "What happened in the last half hour",
7181 description: "One page of the stream — the mesh, the executor's trail and GitHub — with what names you listed first. With no running server the answer is the reason.",
7182 argv: &["monitor", "--since", "30m", "--for", "1b"],
7183 setup: &[],
7184 expect: Expect::StdoutContains(&["no running server"]),
7185 },
7186 ExampleDoc {
7187 id: "monitor-wait",
7188 title: "Wait for a pull request to merge",
7189 description: "Follow the stream and exit 0 at the first merge whose summary names #885; `--timeout` gives up with exit 10, as it does here within a second when no server answers.",
7190 argv: &["monitor", "--follow", "--match", "#885", "--until", "merged", "--timeout", "1s", "--interval", "1"],
7191 setup: &[],
7192 expect: Expect::ExitCode(10),
7193 },
7194 ],
7195 },
7196 CommandExamples {
7197 command: "mesh events",
7198 examples: &[ExampleDoc {
7199 id: "mesh-events",
7200 title: "One page of the cooperation journal",
7201 description: "The journal's signed events above a Lamport stamp; `--after` is the previous page's `lamport`. With no running server the answer is the reason.",
7202 argv: &["mesh", "events", "--after", "0", "--limit", "50"],
7203 setup: &[],
7204 expect: Expect::StdoutContains(&["cooperation inactive"]),
7205 }],
7206 },
7207 CommandExamples {
7208 command: "mesh verify",
7209 examples: &[ExampleDoc {
7210 id: "mesh-verify",
7211 title: "Prove cooperation now, or say why it cannot",
7212 description: "A live round with every peer the server dials and the local checks, each failure with its impact and remedy. It exits 10 when anything fails — here, because no server runs to verify.",
7213 argv: &["mesh", "verify"],
7214 setup: &[],
7215 expect: Expect::ExitCode(10),
7216 }],
7217 },
7218 CommandExamples {
7219 command: "mesh claim",
7220 examples: &[ExampleDoc {
7221 id: "mesh-claim",
7222 title: "Claim paths for a session across the mesh",
7223 description: "An exclusive claim that meets a live exclusive claim on any linked runtime exits 10 with claim_conflict naming it. A claim needs the running server that replicates it; without one the command exits 10 and says so.",
7224 argv: &["mesh", "claim", "docs", "--session", "s1", "--issue", "#184"],
7225 setup: &[],
7226 expect: Expect::ExitCode(10),
7227 }],
7228 },
7229 CommandExamples {
7230 command: "mesh release",
7231 examples: &[ExampleDoc {
7232 id: "mesh-release",
7233 title: "Release a claim this server holds",
7234 description: "Only the holder's current run releases a claim; a dead holder's claim expires instead. Without a running server there is nothing to release, and the command exits 10.",
7235 argv: &["mesh", "release", "stream/c-000000000000"],
7236 setup: &[],
7237 expect: Expect::ExitCode(10),
7238 }],
7239 },
7240 CommandExamples {
7241 command: "mesh session open",
7242 examples: &[ExampleDoc {
7243 id: "mesh-session-open",
7244 title: "Say what a session is doing, to every linked runtime",
7245 description: "Client, intent, issue and branch of a session, replicated to every linked runtime. It needs the running server; without one it exits 10.",
7246 argv: &["mesh", "session", "open", "--session", "s1", "--client", "codex", "--issue", "#184"],
7247 setup: &[],
7248 expect: Expect::ExitCode(10),
7249 }],
7250 },
7251 CommandExamples {
7252 command: "mesh session close",
7253 examples: &[ExampleDoc {
7254 id: "mesh-session-close",
7255 title: "Close a session and end its claims",
7256 description: "Every claim the session holds ends with it, on every linked runtime. It needs the running server; without one it exits 10.",
7257 argv: &["mesh", "session", "close", "--session", "s1"],
7258 setup: &[],
7259 expect: Expect::ExitCode(10),
7260 }],
7261 },
7262 CommandExamples {
7263 command: "mesh handover publish",
7264 examples: &[ExampleDoc {
7265 id: "mesh-handover-publish",
7266 title: "Publish this checkout's newest handover",
7267 description: "The newest record under .ai/local/state/handovers/ travels to every linked runtime, bounded and identified by its body's digest. It needs the running server; without one it exits 10.",
7268 argv: &["mesh", "handover", "publish", "--issue", "#184"],
7269 setup: &[],
7270 expect: Expect::ExitCode(10),
7271 }],
7272 },
7273 CommandExamples {
7274 command: "mesh handover consume",
7275 examples: &[ExampleDoc {
7276 id: "mesh-handover-consume",
7277 title: "Consume a handover another runtime published",
7278 description: "Records the consumption and writes the handover where `majordomus handover --resolve` finds it on the same branch. It needs the running server; without one it exits 10.",
7279 argv: &["mesh", "handover", "consume", "00000000000000000000000000000000", "--session", "s1"],
7280 setup: &[],
7281 expect: Expect::ExitCode(10),
7282 }],
7283 },
7284 CommandExamples {
7285 command: "mesh review request",
7286 examples: &[ExampleDoc {
7287 id: "mesh-review-request",
7288 title: "Ask the mesh for a review",
7289 description: "A named reviewer must be a linked runtime carrying the reviews feature, or the request exits 10 with feature_unsupported. It needs the running server; without one it exits 10.",
7290 argv: &["mesh", "review", "request", "feature/x", "--session", "s1"],
7291 setup: &[],
7292 expect: Expect::ExitCode(10),
7293 }],
7294 },
7295 CommandExamples {
7296 command: "mesh review answer",
7297 examples: &[ExampleDoc {
7298 id: "mesh-review-answer",
7299 title: "Answer a review request from any runtime",
7300 description: "approved, changes_requested or commented, with a note, replicated to every linked runtime. It needs the running server; without one it exits 10.",
7301 argv: &["mesh", "review", "answer", "stream/r-000000000000", "--session", "s1", "--verdict", "approved"],
7302 setup: &[],
7303 expect: Expect::ExitCode(10),
7304 }],
7305 },
7306 CommandExamples {
7307 command: "mesh review withdraw",
7308 examples: &[ExampleDoc {
7309 id: "mesh-review-withdraw",
7310 title: "Withdraw a review request with its result",
7311 description: "Only the runtime that asked may withdraw its request, from any of its sessions; the note is the requester's own result and never an answer. It needs the running server; without one it exits 10.",
7312 argv: &["mesh", "review", "withdraw", "stream/r-000000000000", "--session", "s1", "--note", "superseded"],
7313 setup: &[],
7314 expect: Expect::ExitCode(10),
7315 }],
7316 },
7317 CommandExamples {
7318 command: "models list",
7319 examples: &[ExampleDoc {
7320 id: "models-list",
7321 title: "The declared model catalogue",
7322 description: "Every vendor and model share/models.yaml declares, in declaration order — which is also routing's preference order. Vendors show whether their named credential variable is set: presence only, never a value. An empty catalogue is an answer, not an error.",
7323 argv: &["models", "list"],
7324 setup: &[],
7325 expect: Expect::StdoutContains(&["model(s)"]),
7326 }],
7327 },
7328 CommandExamples {
7329 command: "models route",
7330 examples: &[ExampleDoc {
7331 id: "models-route",
7332 title: "Which model a need selects, and why",
7333 description: "The first declared model satisfying every requirement wins; the qualifying rest are the fallback chain, and every excluded model carries the first check it failed. Pure over the declared data — the same question always gets the same answer, and the reasons are in it.",
7334 argv: &["models", "route", "--require", "text"],
7335 setup: &[],
7336 expect: Expect::StdoutContains(&["selected"]),
7337 }],
7338 },
7339 CommandExamples {
7340 command: "reasoning advisors",
7341 examples: &[ExampleDoc {
7342 id: "reasoning-advisors",
7343 title: "The advisors, and what they can do now",
7344 description: "Every declared advisor with its status and why — available, unavailable, not_configured, disabled, temporarily_failed, rate_limited — from presence alone (an executable on PATH, a credential variable set, never a value), the mode in force and the recorded outcomes of earlier consultations; then who can provide each advisory capability now. Reasoning is operational whether or not any advisor is.",
7345 argv: &["reasoning", "advisors"],
7346 setup: &[],
7347 expect: Expect::StdoutContains(&["reasoning operational"]),
7348 }, ExampleDoc {
7349 id: "reasoning-advisors-json",
7350 title: "The same answer as one document",
7351 description: "The report the API and the MCP tool return: `operational`, the mode and what decided it, every advisor with its status and reason, and the capacity per capability. A script reads this rather than the text form.",
7352 argv: &["reasoning", "advisors", "--format", "json"],
7353 setup: &[],
7354 expect: Expect::Json(&["/operational", "/mode", "/advisors", "/capacity"]),
7355 }],
7356 },
7357 CommandExamples {
7358 command: "reasoning plan",
7359 examples: &[ExampleDoc {
7360 id: "reasoning-plan",
7361 title: "What a material uncertainty calls for",
7362 description: "Whether independent review is worth having, how many advisors the mode allows, which available advisors a capability-driven selection asks, and why every other advisor is left out. With no suitable advisor the plan is the structured local review. Nothing is recorded.",
7363 argv: &["reasoning", "plan", "--materiality", "material"],
7364 setup: &[],
7365 expect: Expect::StdoutContains(&["outcome", "budget"]),
7366 }, ExampleDoc {
7367 id: "reasoning-plan-capabilities",
7368 title: "A high uncertainty that asks for named capabilities",
7369 description: "The selection covers the requested capabilities first, then prefers an advisor reached through a different adapter, then declaration order; every advisor not selected carries its reason. With none available the outcome is the structured local review.",
7370 argv: &["reasoning", "plan", "--materiality", "high", "--capabilities", "independent_reasoning,code_review"],
7371 setup: &[],
7372 expect: Expect::StdoutContains(&["outcome", "budget"]),
7373 }],
7374 },
7375 CommandExamples {
7376 command: "reasoning record",
7377 examples: &[ExampleDoc {
7378 id: "reasoning-record-refused",
7379 title: "Input that is not a record is refused",
7380 description: "The writer reads one JSON record (`{\"kind\":\"assessment\",...}`) from --file or standard input. Anything else — here a YAML file — is refused with exit 13 and nothing is written; so is a record that breaks a rule, such as a plan for an assessment nobody recorded.",
7381 argv: &["reasoning", "record", "--file", "share/advisors.yaml"],
7382 setup: &[],
7383 expect: Expect::ExitCode(13),
7384 }],
7385 },
7386 CommandExamples {
7387 command: "reasoning status",
7388 examples: &[ExampleDoc {
7389 id: "reasoning-status",
7390 title: "The reasoning state of the open task",
7391 description: "Assessments and where each stands, consultations and how each ended, disagreements and what settled them, conclusions with their computed review and validation, and the timeline — derived from the records alone.",
7392 argv: &["reasoning", "status", "--task", "all"],
7393 setup: &[],
7394 expect: Expect::StdoutContains(&["records"]),
7395 }],
7396 },
7397 CommandExamples {
7398 command: "reasoning explain",
7399 examples: &[ExampleDoc {
7400 id: "reasoning-explain-absent",
7401 title: "Why a decision was made",
7402 description: "One record with the whole chain of its assessment. An id nothing recorded is refused as not found.",
7403 argv: &["reasoning", "explain", "conclusion-absent"],
7404 setup: &[],
7405 expect: Expect::ExitCode(13),
7406 }],
7407 },
7408 CommandExamples {
7409 command: "reasoning check",
7410 examples: &[ExampleDoc {
7411 id: "reasoning-check",
7412 title: "Check that reasoning stays provider-independent",
7413 description: "The advisor catalogue's references, the transport adapters, the provider-independent sources, CI, the documents and every stored record; exit 10 on a finding.",
7414 argv: &["reasoning", "check"],
7415 setup: &[],
7416 expect: Expect::StdoutContains(&["checks"]),
7417 }],
7418 },
7419];
7420
7421#[derive(Debug, clap::Args)]
7422pub struct CommitArgs {
7454 #[command(flatten)]
7455 pub repo: RepoArgs,
7457
7458 #[command(subcommand)]
7459 pub command: Option<CommitCommand>,
7461
7462 #[arg(long, value_enum, default_value_t = OutputFormat::Text, global = true)]
7463 pub format: OutputFormat,
7465}
7466
7467#[derive(Debug, Subcommand)]
7468pub enum CommitCommand {
7500 Plan,
7502 Scopes,
7504 History {
7506 #[arg(value_name = "RANGE")]
7508 range: Option<String>,
7509 },
7510 Validate {
7512 #[arg(value_name = "FILE")]
7514 file: Option<String>,
7515
7516 #[arg(long, value_name = "PATHS", value_delimiter = ',')]
7518 paths: Vec<String>,
7519
7520 #[arg(long, value_name = "REV", conflicts_with = "file")]
7522 rev: Option<String>,
7523 },
7524}
7525
7526#[cfg(test)]
7527mod tests {
7528 use super::*;
7529 use clap::Parser;
7530
7531 fn view(args: &[&str]) -> MeshViewArgs {
7532 let cli = Cli::try_parse_from(["majordomus", "mesh", "state"].iter().chain(args))
7533 .expect("the flags parse");
7534 let Command::Mesh(mesh) = cli.command else {
7535 panic!("expected `mesh`")
7536 };
7537 let MeshCommand::State(view) = mesh.command else {
7538 panic!("expected `state`")
7539 };
7540 view
7541 }
7542
7543 #[test]
7546 fn every_mesh_view_flag_is_one_query_pair_in_declared_order() {
7547 let all = view(&[
7548 "--matching",
7549 "src/x.rs",
7550 "--open",
7551 "--limit",
7552 "5",
7553 "--kind",
7554 "claims",
7555 "--runtime",
7556 "n1-r1",
7557 "--session",
7558 "s-1",
7559 "--after",
7560 "42",
7561 "--live-claims",
7562 "--full",
7563 ]);
7564 assert_eq!(
7565 all.pairs(),
7566 [
7567 "view=full",
7568 "claims=live",
7569 "after=42",
7570 "session=s-1",
7571 "runtime=n1-r1",
7572 "kind=claims",
7573 "limit=5",
7574 "open=true",
7575 "matching=src/x.rs",
7576 ]
7577 );
7578 assert!(view(&[]).pairs().is_empty());
7579 }
7580
7581 #[test]
7584 fn a_duration_is_read_in_its_unit_and_refused_in_words() {
7585 assert_eq!(parse_duration(" 90 "), Ok(90));
7586 assert_eq!(parse_duration("2d"), Ok(172_800));
7587 let not_a_number = parse_duration("soon").unwrap_err();
7588 assert!(not_a_number.contains("is not a duration"), "{not_a_number}");
7589 let unknown = parse_duration("3w").unwrap_err();
7590 assert!(unknown.contains("unknown unit"), "{unknown}");
7591 }
7592}