Skip to main content

Graph

Struct Graph 

Source
pub struct Graph {
Show 34 fields pub github_text_guard: bool, pub github_language: String, pub implementers: usize, pub selected_implementer: Option<String>, pub judges: usize, pub deliberate_rounds: usize, pub reviewers: usize, pub review_rounds: usize, pub gate_fix_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_verify: Option<u64>, pub timeout_fix: u64, pub timeout_talk: u64, pub timeout_resource_wait: u64, pub retries: usize, pub worktree_root: Option<PathBuf>, pub land: bool, pub land_rounds: usize, pub rerun_flaky_checks: bool, pub land_approval: bool, pub hold_contested_merge: bool, pub file_followups: bool, pub release_deputy_followups: bool, pub answer_timeout: u64, pub incomplete_review: IncompleteReviewPolicy, pub e2e_every_round: bool, pub advise: bool, pub advisors: usize, pub graft_runner_up: bool,
}
Expand description

Graph shape and limits.

Fields§

§github_text_guard: bool

Gate GitHub prose before posting. Secret redaction remains mandatory when disabled.

§github_language: String

Language of pull request / issue titles, bodies and GitHub comments (en / ja / any language name). Default en. Anything but English switches off the posting gate’s English-only language check for those texts (secret redaction stays); commit messages are always English. Independent of Self::language, which is for the operator.

§implementers: usize

Parallel implementations of the same task (the number of implementer seats; pairs with Roles::implementers). One by default.

Formerly candidates, still read as a deprecated alias.

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.

§selected_implementer: Option<String>

Durable owner selection for a replacement implementation. No fallback.

§judges: usize

Independent judges.

§deliberate_rounds: usize

Deliberation rounds when the judges’ first choices disagree.

§reviewers: usize

Reviewers 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::implementers’s doc describes as running on every task regardless of competition, which is what makes a panel worth its cost here even though implementers itself defaults to one.

§review_rounds: usize

Maximum review+fix rounds before the run is declared blocked.

§gate_fix_rounds: usize

Fix rounds a failing verify.gate gets before the run is blocked. The fixer is handed the gate’s own output; 0 keeps the old behaviour of blocking on the first red gate. Independent of Self::review_rounds so a run that spent its review budget can still repair a one-line gate failure.

§max_parallel: usize

Maximum agent processes running at once.

§language: String

Language for the prose the agents write (en / ja / any language name).

§sessions: bool

Keep 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: u64

Per-node timeouts, seconds.

§timeout_judge: u64

Per-node timeouts, seconds.

§timeout_review: u64

Per-node timeouts, seconds.

§timeout_verify: Option<u64>

Timeout for verify.e2e and verify.gate, seconds. Separate from Self::timeout_review so shrinking a reviewer’s budget cannot silently shrink a real-machine command’s budget too — the two used to share timeout_review, and turning a slow reviewer down cut the timeout cargo test --all-targets runs under along with it. When omitted, preserves legacy configurations by using Self::timeout_review. Set an explicit value to make verification independent of later review-seat budget changes.

§timeout_fix: u64

Per-node timeouts, seconds.

§timeout_talk: u64

Wall-clock limit for one turn of crate::talk’s standing conversation, seconds.

An hour: the operator is not watching this turn resolve in real time, so the budget can match what the work - reading files, running commands, checking their output - actually needs rather than what a person waiting on a phone can tolerate.

§timeout_resource_wait: u64

Longest an agent seat or verification batch may wait for the shared build cache’s lease before starting, seconds.

A separate clock from every timeout_* above: those start when the CLI or verification command is spawned and never include this wait. Expiry is a resource block (a resumable hold that spends no attempt and rotates no agent), not an agent timeout.

§retries: usize

Retries for an agent invocation that fails or returns nothing usable.

§worktree_root: Option<PathBuf>

Root for candidate / judge worktrees. Defaults to ~/wt/magi.

§land: bool

After 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: usize

Land rounds - watch, fix, push - before the run is left for a human.

§rerun_flaky_checks: bool

When land sees a required check fail on the head it is bound to, rerun that check’s workflow run once (gh run rerun <id> --failed) before spending a fix round on it. A run id is rerun at most once, recorded before the call, and forgotten when the head moves; the rerun costs no fix round and no attempt. A failure with no workflow run (an external status) goes straight to the fixer. On; off sends every red check to the fixer at once.

§land_approval: bool

Ask 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.

§hold_contested_merge: bool

Ask the owner when open Major-or-above internal findings OR a final rejecting reviewer vote remain. Final votes use reconsideration when answered, otherwise the initial vote. On by default; even a reject with zero Major findings requires approval when this control is enabled.

land_approval independently asks about every merge. With both controls off, new ordinary approvals are skipped. Neither control bypasses an existing question or owner decision, nor the fresh approval required after merge repair (including repair that leaves the head unchanged). The pull request is opened either way; only the merge waits.

§file_followups: bool

After a run’s pull request merges, file the findings its last review round left open as follow-up tasks (crate::followup) instead of letting them vanish with the merge: every Major-or-above finding, and every finding of a seat whose final vote was reject. Other Minor/Nit findings are only listed in the pull-request comment. Does not affect whether the merge happens. On; best-effort, a failure is a run event.

§release_deputy_followups: bool

After a run’s pull request merges, release the follow-up tasks the merge approval’s deputy filed held for that pull request (crate::followup::settle_deputy_tasks): only a task the deputy filed for this run whose hold reason names this pull request, exactly once, and never one that duplicates an automatic follow-up (that one is left held with the reason). The generation cap applies. Independent of file_followups. On; off leaves them held until magi task release.

§answer_timeout: u64

How 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: IncompleteReviewPolicy

What a round does when one or more reviewer seats never answered (timeout, crash, unparsable output).

§e2e_every_round: bool

Run verify.e2e on every round, even one that already has blocking findings and another round left to try.

Off by default: a round with a blocking finding and rounds still left is going back to the fixer regardless of what verify.e2e says, so running it first only spends the round’s slowest step (minutes, on a Rust repo’s cargo test --all-targets) on a head about to be rewritten anyway. verify.e2e still runs once a round has no blocking findings left (a round cannot go clean without it) and the final verify.gate always runs on the actual tree that would land — deferring is about when e2e runs mid-loop, never about skipping it.

Set this to restore the old every-round diagnostic behaviour: e2e output from a round that still has blocking findings is occasionally useful on its own (a runtime failure a reviewer’s panel would not have caught by reading), and this is the way back to seeing it every round instead of only once the panel has nothing left to flag.

§advise: bool

Run the design-deliberation stage before implement: independent advisor seats each sketch a design, and (when at least one produced a usable proposal) a synthesis blends them into a brief carried in the implementer’s prompt. See graph::Runner::advise.

On by default. A design sketch is a few paragraphs an agent can write without touching the repository, where a full implementation is a tool loop that re-reads the codebase on every turn - so three sketches, gathered once before implement starts, cost a fraction of a fourth candidate and buy back a form of the same disagreement Self::implementers’s doc describes moving away from being the default, on every run rather than only the ones an operator remembers to ask for with --implementers.

§advisors: usize

How many independent design proposals the deliberation stage gathers. Three by default - the same number Self::implementers’s doc names as the point where a fourth judge’s first choice stopped changing the tally.

§graft_runner_up: bool

After the tally picks a winner and before the review loop, a fixer round ports the strengths the judges explicitly attributed to the losing candidates onto the winner (graph::Runner::graft). Skipped for a single candidate, a run with no winner or no quorum, and when no judge recorded a strength for a loser. Best-effort: a failure, a quota hit or no change restores the winner’s pre-graft commit and the run carries on as if this were off. On by default.

Implementations§

Source§

impl Graph

Source

pub fn verify_timeout(&self) -> u64

Effective machine-command budget. Older configuration files had only timeout_review, which also governed verification, so absence is a compatibility fallback rather than a new 1200-second default.

Source

pub fn language_gate(&self) -> bool

Does the posting gate enforce English on GitHub text? The one place that decides it: the guard is on and github_language is English.

Source

pub fn github_english(&self) -> bool

Is GitHub text English (the default), whether or not the gate is on?

Trait Implementations§

Source§

impl Clone for Graph

Source§

fn clone(&self) -> Self

Returns a duplicate of the value. Read more
1.0.0 (const: unstable) · Source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
Source§

impl Debug for Graph

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
Source§

impl Default for Graph

Source§

fn default() -> Self

Returns the “default value” for a type. Read more
Source§

impl<'de> Deserialize<'de> for Graph
where Graph: Default,

Source§

fn deserialize<__D>(__deserializer: __D) -> Result<Self, __D::Error>
where __D: Deserializer<'de>,

Deserialize this value from the given Serde deserializer. Read more
Source§

impl Serialize for Graph

Source§

fn serialize<__S>(&self, __serializer: __S) -> Result<__S::Ok, __S::Error>
where __S: Serializer,

Serialize this value into the given Serde serializer. Read more

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> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> CloneToUninit for T
where T: Clone,

Source§

unsafe fn clone_to_uninit(&self, dest: *mut u8)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dest. Read more
Source§

impl<T> DeserializeOwned for T
where T: for<'de> Deserialize<'de>,

Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T> FromRef<T> for T
where T: Clone,

Source§

fn from_ref(input: &T) -> T

Converts to this type from a reference to the input type.
Source§

impl<T> Instrument for T

Source§

fn instrument(self, span: Span) -> Instrumented<Self> ⓘ

Instruments this type with the provided Span, returning an Instrumented wrapper. Read more
Source§

fn in_current_span(self) -> Instrumented<Self> ⓘ

Instruments this type with the current Span, returning an Instrumented wrapper. Read more
Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> IntoEither for T

Source§

fn into_either(self, into_left: bool) -> Either<Self, Self> ⓘ

Converts 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 more
Source§

fn into_either_with<F>(self, into_left: F) -> Either<Self, Self> ⓘ
where F: FnOnce(&Self) -> bool,

Converts 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
Source§

impl<T> PolicyExt for T
where T: ?Sized,

Source§

fn and<P, B, E>(self, other: P) -> And<T, P>
where T: Sized + Policy<B, E>, P: Policy<B, E>,

Create a new Policy that returns Action::Follow only if self and other return Action::Follow. Read more
Source§

fn or<P, B, E>(self, other: P) -> Or<T, P>
where T: Sized + Policy<B, E>, P: Policy<B, E>,

Create a new Policy that returns Action::Follow if either self or other returns Action::Follow. Read more
Source§

impl<T, S> SimdFrom<T, S> for T
where S: Simd,

Source§

fn simd_from(_simd: S, value: T) -> T

Source§

impl<F, T, S> SimdInto<T, S> for F
where T: SimdFrom<F, S>, S: Simd,

Source§

fn simd_into(self, simd: S) -> T

Source§

impl<T> ToOwned for T
where T: Clone,

Source§

type Owned = T

The resulting type after obtaining ownership.
Source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
Source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = !

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, !>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
Source§

impl<T> WithSubscriber for T

Source§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self> ⓘ
where S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a WithDispatch wrapper. Read more
Source§

fn with_current_subscriber(self) -> WithDispatch<Self> ⓘ

Attaches the current default Subscriber to this type, returning a WithDispatch wrapper. Read more