use super::Error;
use crate::template::GitRunner;
use std::path::Path;
pub(crate) const GOAL_FILE: &str = "goal.md";
pub(crate) const SOUL_FILE: &str = "soul.md";
pub(crate) struct SpawnRequest<'a> {
pub(crate) parent_worktree: &'a Path,
pub(crate) parent_branch: &'a str,
pub(crate) sub_branch: &'a str,
pub(crate) sub_worktree: &'a Path,
pub(crate) fork_point: Option<&'a str>,
pub(crate) goal_text: &'a str,
pub(crate) soul_text: Option<&'a str>,
pub(crate) granted: &'a [String],
pub(crate) commit_subject: &'a str,
}
pub(crate) fn spawn_subagent_branch(
req: &SpawnRequest<'_>,
git: &dyn GitRunner,
) -> Result<(), Error> {
let wt_str = req.sub_worktree.to_string_lossy().to_string();
let sub_ref = crate::workspace::agent_ref(req.sub_branch);
let parent_ref = crate::workspace::agent_ref(req.parent_branch);
let start = req.fork_point.unwrap_or(parent_ref.as_str());
git.run(
req.parent_worktree,
&[
"worktree",
"add",
"-b",
sub_ref.as_str(),
wt_str.as_str(),
start,
],
)
.map_err(|source| Error::Git {
op: "worktree add",
source,
})?;
std::fs::create_dir_all(req.sub_worktree)?;
crate::prompt::dispatch::trim_to_context(req.sub_worktree, req.granted, git)?;
std::fs::write(req.sub_worktree.join(GOAL_FILE), req.goal_text)?;
if let Some(soul) = req.soul_text {
std::fs::write(req.sub_worktree.join(SOUL_FILE), soul)?;
}
let mut add_args: Vec<&str> = vec!["add", GOAL_FILE];
if req.soul_text.is_some() {
add_args.push(SOUL_FILE);
}
git.run(req.sub_worktree, &add_args)
.map_err(|source| Error::Git { op: "add", source })?;
git.run(req.sub_worktree, &["commit", "-m", req.commit_subject])
.map_err(|source| Error::Git {
op: "commit",
source,
})?;
Ok(())
}
#[cfg(test)]
mod tests;