Skip to main content

magi/
lib.rs

1//! magi — a blind multi-agent implementation competition.
2//!
3//! One task, several agents, and a graph that decides which implementation
4//! survives without a human reading the diff:
5//!
6//! 1. **implement** — N agents solve the same task in isolated git worktrees,
7//!    unaware of each other.
8//! 2. **judge** — M judges rank the candidates blind: labels `A`/`B`/`C`, a
9//!    per-judge presentation order, attribution trailers stripped at write time
10//!    by a `commit-msg` hook and again at presentation time.
11//! 3. **deliberate** — if the first choices disagree, the judges argue, with
12//!    magi as the facilitator. A facilitator made of code cannot leak an author.
13//! 4. **vote** — final votes are collected one-to-one and privately, so nobody
14//!    can drift toward a visible majority.
15//! 5. **review** — the winner enters a bounded review + real-machine
16//!    verification loop with a fixer that may reject a finding with an argument.
17//! 6. **gate** — configured commands must pass before anything merges.
18//!
19//! Everything is recorded, so the by-products are real numbers: per-agent win
20//! rates, per-reviewer precision, and how often execution caught what static
21//! review missed. See [`stats`].
22#![deny(missing_docs)]
23
24pub mod advise;
25pub mod agent;
26pub mod already;
27pub mod ask;
28mod base_sync_recovery;
29pub mod blind;
30pub mod blockers;
31pub mod bump;
32pub mod cache;
33pub mod chat_control;
34mod chat_merge;
35pub mod chat_notify;
36pub mod chat_watch;
37pub mod clean;
38pub mod conduct;
39pub mod config;
40pub mod consult;
41pub mod daemon;
42pub mod deputy;
43pub mod direct;
44pub mod disk;
45mod driver;
46pub mod dupes;
47pub mod fixer;
48mod fold_evidence;
49pub mod followup;
50pub mod foreign_checkout;
51pub mod git;
52pub mod github_text;
53pub mod graft;
54pub mod graft_report;
55pub mod graph;
56pub mod handover;
57mod id_reserve;
58pub mod land;
59pub mod lang;
60mod lock_file;
61pub mod md;
62pub mod merge_decision;
63pub mod notice_delivery;
64mod notice_semantics;
65pub mod notices;
66pub mod persona;
67pub mod persona_icon;
68mod pr_head;
69pub mod pr_outcome;
70pub mod pr_recovery;
71pub mod proc;
72pub mod prompt;
73pub mod question_delivery;
74pub mod queue;
75pub mod rebase;
76pub mod reconcile;
77pub mod recovery;
78pub mod refs;
79pub mod release_local;
80pub mod release_manifest;
81pub mod release_watch;
82pub mod repair_budget;
83pub mod repo_clone;
84mod repo_lock;
85pub mod report;
86pub mod report_view;
87pub mod repos;
88pub mod retention;
89pub mod review_repair;
90pub mod rng;
91pub mod run;
92pub mod run_progress;
93pub mod scrub;
94mod seat_process;
95pub mod settings;
96/// Explicit audit-only repair of never-executed startup reservations.
97pub mod startup_reconcile;
98pub mod stats;
99mod stop_reason;
100pub mod talk;
101pub mod task_chat;
102pub mod triage;
103pub mod tui;
104pub mod updater;
105pub mod verdict;
106pub mod waiter;
107pub mod web;
108pub mod worker;
109pub mod worktree_setup;
110
111pub mod choice_effect;
112mod resume;
113
114// Run environment-sensitive unit fixtures as ordinary standalone invocations,
115// without mutating the concurrent test harness or inheriting worker ownership.
116#[cfg(test)]
117pub(crate) fn standalone_test(name: &str) -> bool {
118    const CHILD: &str = "MAGI_STANDALONE_TEST";
119    if std::env::var(CHILD).as_deref() == Ok(name) {
120        return true;
121    }
122    let mut command = std::process::Command::new(std::env::current_exe().expect("test executable"));
123    for key in worker::INVOCATION_ENV {
124        command.env_remove(key);
125    }
126    let output = command
127        .args(["--exact", name, "--nocapture"])
128        .env(CHILD, name)
129        .output()
130        .expect("standalone test process");
131    assert!(
132        output.status.success() && String::from_utf8_lossy(&output.stdout).contains("1 passed"),
133        "standalone test {name} failed: {}\n{}\n{}",
134        output.status,
135        String::from_utf8_lossy(&output.stdout),
136        String::from_utf8_lossy(&output.stderr)
137    );
138    false
139}