pub struct LoopCfg {Show 27 fields
pub max_rounds: u32,
pub auto_merge: bool,
pub first_implementor: Option<String>,
pub base_branch: String,
pub worktrees: bool,
pub keep_worktrees: bool,
pub state_store: StateStore,
pub branch_prefix: String,
pub followups: Followups,
pub file_non_blocking: bool,
pub max_followups: usize,
pub max_split_parts: usize,
pub file_nits: bool,
pub close_skipped: bool,
pub parallel_triage: bool,
pub min_number: i64,
pub absorb_new_issues: u32,
pub decompose_trackers: bool,
pub max_tracker_children: usize,
pub drafts: Drafts,
pub instructions: String,
pub max_issue_chars: usize,
pub max_triage_chars: usize,
pub checkin_trust: Trust,
pub checkin_resolve: bool,
pub max_checkin_comments: usize,
pub effort_schedule: EffortSchedule,
}Expand description
Every field takes its value from LoopCfg::default() when a config does not
mention it, rather than from a per-field function saying the same thing in a
second place. Two places is how a default goes stale.
Fields§
§max_rounds: u32Review rounds one invocation may spend asking for changes. A run that spends the full budget may use one closing pass, which is not a round.
auto_merge: bool§first_implementor: Option<String>§base_branch: String§worktrees: bool§keep_worktrees: bool§state_store: StateStore§branch_prefix: String§followups: Followups§file_non_blocking: boolFile a non-blocking finding as a follow-up.
Off by default, and this is the setting that stops a run breeding. A thorough reviewer always finds improvements, and turning each one into a tracker item made a single issue spawn ten, which spawned more: mean offspring above one never terminates. Not gating a merge is not the same as being worth somebody’s triage queue.
max_followups: usizeMost follow-ups one run may record before it stops and says what it dropped. A backstop, not a target.
max_split_parts: usizeMost parts spar split will make out of one issue or pull request.
A backstop, not a target, in the shape of max_followups. There is no
setting to turn splitting off: it is a command somebody types, and a
setting to disable a command nobody has to run only ever confuses. There
is no mechanical threshold either, because a floor on files changed
would split a forty file rename and hold back a three file mess.
file_nits: boolNits stay in the PR thread by default. A filed nit is somebody else’s notification: a run on a production codebase once opened an issue titled “Log wording”.
close_skipped: boolClose an issue that both agents independently declined, after posting the shared reasoning. One agent’s opinion is never enough.
parallel_triage: boolAsk both agents to triage at the same time. They only read during triage, so there is nothing to serialise.
min_number: i64Ignore issues and pull requests numbered below this when spar is picking for itself. 0 is no floor.
A repository that has been going a while carries a tail of old issues nobody is going to reach, and since spar takes the lowest numbered open items it walks straight into them. A number you name explicitly is still honoured: naming it is the point.
absorb_new_issues: u32Waves of newly filed follow-ups to fold back into the same run, rather than leaving them for the next one.
Off by default because it multiplies what a run costs, and because each wave can file follow-ups of its own. Every wave is triaged like any other issue, so both agents still have to agree it is worth doing.
decompose_trackers: boolTurn the checklist in a tracking issue into issues, and work them.
Off by default, for the reason file_non_blocking is: a tracker exists
to contain many things, so this is the shape of feature that multiplies.
max_tracker_children caps it, a child that triage calls a tracker is
held rather than decomposed in turn, and both agents still gate every
child at triage.
The trigger is the checklist, never a judgement about what the parts
are. Writing - [ ] lines is something a person does on purpose, which
makes this opt in per issue as well as per repository.
max_tracker_children: usizeMost items from one tracker’s checklist that one run may take on. A cap, not a target, and what it left is named out loud.
drafts: DraftsWhether a pull request spar opens starts as a draft.
instructions: StringExtra instructions handed to both agents with every request.
For what a person wants of this repository that the code cannot say and spar has no setting for: how far to go, what not to touch, what not to wait on. A CLI reads its own conventions file already, CLAUDE.md or AGENTS.md, but each reads only its own, and two agents given different standing instructions are not the pair this design rests on.
Subordinate to the request and to the schema, which is said in the header they arrive under: they change how the work is done, never what was asked for or the shape of the answer.
max_issue_chars: usizeThe most of one issue body that reaches a prompt.
Sized so that no issue a person wrote is ever cut. It was 2000 for triage and 6000 for implement, silently, and both were small enough to clip an ordinary bug report: an agent given half an issue judges and implements the half it saw and has no way to know the rest existed. When this does fire it is said out loud, in the log and in the prompt.
max_triage_chars: usizeThe most every issue body together may add to one triage prompt.
Triage reads the whole queue at once, so the only unbounded thing here is the queue. Past this, whole issues are left for the next run rather than every issue being shortened: a verdict is posted on the issue and can close it, so judging one on part of its body is worse than not reaching it yet.
checkin_trust: TrustWhose comments spar checkin will act on.
checkin_resolve: boolMark a review thread resolved when spar made the change it asked for.
A thread spar disagreed with is left open whatever this says: the person who raised it has not had their say yet, and it is their thread.
max_checkin_comments: usizeMost unanswered comments spar answers on one pull request in a run.
A backstop against a long argument being read back to somebody, not a target. What it held back is said out loud.
effort_schedule: EffortSchedule