use std::fmt::Write as _;
use trusty_mpm::core::agent_metadata::agent_metadata_from_str;
use trusty_mpm::core::bundle::ALL;
pub(crate) fn render() -> String {
let mut agents: Vec<(String, trusty_mpm::core::agent_metadata::AgentMetadata)> = ALL
.iter()
.filter(|a| a.rel_path.starts_with("agents/") && !a.rel_path.starts_with("agents/BASE-"))
.map(|a| {
let stem = a
.rel_path
.strip_prefix("agents/")
.and_then(|s| s.strip_suffix(".md"))
.unwrap_or(a.rel_path)
.to_string();
(stem, agent_metadata_from_str(a.contents))
})
.collect();
agents.sort_by(|(a, _), (b, _)| a.cmp(b));
let mut out = String::new();
out.push_str("# Agent Roster Reference\n\n");
out.push_str(
"Generated from `bundle::ALL` (filtered to `agents/*.md`) + \
`agent_metadata::agent_metadata_from_str` — the same frontmatter \
parser `agent_builder` uses at compose time. Regenerate with \
`tm generate capabilities`.\n\n",
);
out.push_str(
"Every agent below transitively `extends: base-agent` (directly, or \
via `base-engineer`/`base-qa`/`base-ops`/`base-research`) — see \
`agents/BASE-AGENT.md` and its four role-specific bases for the \
shared foundation, not repeated per row here.\n\n",
);
let _ = writeln!(out, "{} concrete agents.\n", agents.len());
out.push_str(
"| Agent | Role | Extends | Description | Declared Skills |\n|---|---|---|---|---|\n",
);
for (stem, meta) in &agents {
let role = meta.role.clone().unwrap_or_default();
let extends = meta.extends.clone().unwrap_or_default();
let description = meta.description.clone().unwrap_or_default();
let skills = meta.skills.join(", ");
let _ = writeln!(
out,
"| `{stem}` | {role} | {extends} | {description} | {skills} |"
);
}
out
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn agents_render_contains_known_agent() {
let rendered = render();
assert!(rendered.contains("`rust-engineer`"), "{rendered}");
assert!(rendered.contains("`code-critic`"), "{rendered}");
}
#[test]
fn agents_render_excludes_base_files() {
let rendered = render();
assert!(!rendered.contains("`BASE-AGENT`"), "{rendered}");
assert!(!rendered.contains("`BASE-ENGINEER`"), "{rendered}");
}
#[test]
fn agents_render_is_deterministic() {
assert_eq!(render(), render());
}
}