use super::{GitRunner, Path, PathBuf, agent_ref, repo_git};
pub fn agent_exists(workspace: &Path, agent_id: &str, git: &dyn GitRunner) -> bool {
let refspec = format!("refs/heads/{}", agent_ref(agent_id));
git.run(
&repo_git(workspace),
&["rev-parse", "--verify", "--quiet", &refspec],
)
.is_ok()
}
#[derive(Debug, thiserror::Error)]
#[error(
"no agent {id:?} in this workspace — {reason}; check the id against the workspace's \
`agents/*` refs, or start an agent with `lernie prompt` / `lernie dispatch`"
)]
pub struct UnknownAgent {
id: String,
reason: &'static str,
}
pub fn require_agent(
workspace: &Path,
agent_id: &str,
reason: &'static str,
git: &dyn GitRunner,
) -> Result<(), UnknownAgent> {
if agent_exists(workspace, agent_id, git) {
return Ok(());
}
Err(UnknownAgent {
id: agent_id.to_owned(),
reason,
})
}
#[derive(Debug, thiserror::Error)]
pub enum LayoutError {
#[error(
"{0} uses the retired per-conversation layout (a `root/` primary worktree with \
control files at the repo root); the current layout is one repo per workspace — \
`<workspace>/repo.git` (bare) with `config/*` branches and `agents/*` refs \
(ARCH §2.2). Pre-v1 clean break (§10): no migration — create a fresh workspace \
with `lernie new` and re-author its config"
)]
OldLayout(PathBuf),
#[error("{0} is not a workspace (no repo.git) — create one with `lernie new` (ARCH §2.2)")]
NotAWorkspace(PathBuf),
}
pub fn require(workspace: &Path) -> Result<(), LayoutError> {
if repo_git(workspace).is_dir() {
return Ok(());
}
if workspace.join("root").join(".git").exists() {
return Err(LayoutError::OldLayout(workspace.to_path_buf()));
}
Err(LayoutError::NotAWorkspace(workspace.to_path_buf()))
}