pub struct Graph {Show 21 fields
pub candidates: usize,
pub judges: usize,
pub deliberate_rounds: usize,
pub reviewers: usize,
pub review_rounds: usize,
pub max_parallel: usize,
pub language: String,
pub sessions: bool,
pub timeout_implement: u64,
pub timeout_judge: u64,
pub timeout_review: u64,
pub timeout_fix: u64,
pub retries: usize,
pub worktree_root: Option<PathBuf>,
pub land: bool,
pub land_rounds: usize,
pub land_approval: bool,
pub answer_timeout: u64,
pub incomplete_review: IncompleteReviewPolicy,
pub advise: bool,
pub advisors: usize,
}Expand description
Graph shape and limits.
Fields§
§candidates: usizeParallel implementations of the same task. One by default.
Competition is the thing magi is for, and it is still here - it is just no longer what every task buys without being asked. Three days and 13 runs on this repository, which is the workload these numbers are drawn from:
- 0 of 13 competed runs reached a merge. Everything that landed in
that window went through
magi review- the cheap half, no competition - and passed on the first try. - The judges’ first choices split 73% of the time (8 of 11 tallies). Candidates that close together make the ranking a weak signal for what it costs to produce.
- One run’s own breakdown: implement 60min, judge 40min, fix 40min, review 28min, verify 5min - and verify is the node that caught a defect every reviewer had passed as clean. The cheapest step is the one that earns its place every time.
It is not worthless: oc won 3 of those tallies against sonnet, so a
single-seat default would have shipped the worse implementation in
roughly a quarter of them. That is exactly why this is a default and
not a removal - magi run --candidates N and a per-task seat count are
how a task that deserves a competition gets one.
A single-candidate run needs no special case: Runner::review’s doc
records that execute already degrades to implement -> review -> gate
-> merge, because judge skips a one-candidate field, deliberate has
no two first choices to reconcile and vote returns early.
judges: usizeIndependent judges.
deliberate_rounds: usizeDeliberation rounds when the judges’ first choices disagree.
reviewers: usizeReviewers per review round. Three by default - the smallest panel
a lens cycle (see crate::prompt::Lens) covers exactly once, so the
default panel reads the patch for spec compliance, regressions, and
simplicity without repeating an angle. Review is also the one stage
Self::candidates’s doc describes as running on every task
regardless of competition, which is what makes a panel worth its cost
here even though candidates itself defaults to one.
review_rounds: usizeMaximum review+fix rounds before the run is declared blocked.
max_parallel: usizeMaximum agent processes running at once.
language: StringLanguage for the prose the agents write (en / ja / any language name).
sessions: boolKeep one CLI conversation per seat, so a judge remembers its own argument across deliberation rounds and the fixer remembers its own implementation across review rounds.
Sessions are scoped to a seat, never to an agent id: the same model sitting as implementer and as judge gets two unrelated conversations, which is what keeps blind judging blind.
timeout_implement: u64Per-node timeouts, seconds.
timeout_judge: u64Per-node timeouts, seconds.
timeout_review: u64Per-node timeouts, seconds.
timeout_fix: u64Per-node timeouts, seconds.
retries: usizeRetries for an agent invocation that fails or returns nothing usable.
worktree_root: Option<PathBuf>Root for candidate / judge worktrees. Defaults to ~/wt/magi.
land: boolAfter the pull request is open, keep going: watch its checks and reviews, run a fix round when they are unhappy, and ask to merge.
On, because stopping at an open pull request left the operator doing
the watching by hand - six times in the session this was built in - and
that is the work the loop exists to take. It only engages for
merge = "pr"; every other merge mode ends the run as before.
Turning this on does not hand magi the merge button:
Graph::land_approval is on too, and nothing merges without an
explicit answer. Setting both to their non-defaults is the only way to
get an unattended merge, and it has to be chosen twice.
land_rounds: usizeLand rounds - watch, fix, push - before the run is left for a human.
land_approval: boolAsk the owner before merging, showing what is about to land.
On, and it is what makes land safe to have on: the question carries a
rendered panel - the diffstat, the patch, the checks, the review
comments that were addressed, and the subject the squash will use - so
the decision is made on evidence rather than on trust, from wherever
the operator happens to be.
Silence is a hold. An unanswered approval never merges, and neither
does any answer other than the word merge.
answer_timeout: u64How long to wait for an owner to answer a question before the run is abandoned, seconds. A parked run costs nothing, so this is generous; it exists so a forgotten question cannot pin a worktree forever.
incomplete_review: IncompleteReviewPolicyWhat a round does when one or more reviewer seats never answered (timeout, crash, unparsable output).
advise: boolRun magi plan’s design-deliberation stage: independent advisors
sketch a design each, headless, and the planner seat synthesizes them
into the task file’s ## Context and ## Change. See
crate::advise.
On by default, and that is the point of this whole stage: candidate
diversity moved here from implement (see Graph::candidates’s
doc) precisely because a design sketch is a few paragraphs, not a
tool loop - so the competition magi is for is cheap enough to run on
every task again, not just the ones an operator remembers to ask for.
advisors: usizeHow many independent design proposals the deliberation stage gathers.
Three by default - the number Graph::candidates’s doc names as
the point where a fourth judge’s first choice stopped changing the
tally.
Trait Implementations§
Source§impl<'de> Deserialize<'de> for Graph
impl<'de> Deserialize<'de> for Graph
Source§fn deserialize<__D>(__deserializer: __D) -> Result<Self, __D::Error>where
__D: Deserializer<'de>,
fn deserialize<__D>(__deserializer: __D) -> Result<Self, __D::Error>where
__D: Deserializer<'de>,
Auto Trait Implementations§
impl Freeze for Graph
impl RefUnwindSafe for Graph
impl Send for Graph
impl Sync for Graph
impl Unpin for Graph
impl UnsafeUnpin for Graph
impl UnwindSafe for Graph
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
Source§impl<T> CloneToUninit for Twhere
T: Clone,
impl<T> CloneToUninit for Twhere
T: Clone,
impl<T> DeserializeOwned for Twhere
T: for<'de> Deserialize<'de>,
Source§impl<T> Instrument for T
impl<T> Instrument for T
Source§fn instrument(self, span: Span) -> Instrumented<Self> ⓘ
fn instrument(self, span: Span) -> Instrumented<Self> ⓘ
Source§fn in_current_span(self) -> Instrumented<Self> ⓘ
fn in_current_span(self) -> Instrumented<Self> ⓘ
Source§impl<T> IntoEither for T
impl<T> IntoEither for T
Source§fn into_either(self, into_left: bool) -> Either<Self, Self> ⓘ
fn into_either(self, into_left: bool) -> Either<Self, Self> ⓘ
self into a Left variant of Either<Self, Self>
if into_left is true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read moreSource§fn into_either_with<F>(self, into_left: F) -> Either<Self, Self> ⓘ
fn into_either_with<F>(self, into_left: F) -> Either<Self, Self> ⓘ
self into a Left variant of Either<Self, Self>
if into_left(&self) returns true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read more