#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum Host {
ClaudeCode,
Codex,
}
impl Host {
pub const ALL: [Self; 2] = [Self::ClaudeCode, Self::Codex];
pub const fn directory(self) -> &'static str {
match self {
Self::ClaudeCode => ".claude/skills/loft-spec",
Self::Codex => ".agents/skills/loft-spec",
}
}
}
const CODEX_ADAPTATION: &str = "agents/openai.yaml";
const FRAGMENT: &str = "agents/claude/frontmatter.yaml";
const ROUTE: &str = "agents/claude/route.md";
const HOST_REFERENCE: &str = "agents/claude/claude-host.md";
const COMPOSED_REFERENCE: &str = "references/claude-host.md";
const ANCHOR: &str = "references/the-loop.md";
const OWNED: [&str; 2] = ["name", "description"];
const LISTING_BUDGET: usize = 1536;
#[derive(Debug, PartialEq, Eq)]
pub enum ComposeError {
Missing(&'static str),
NoFrontmatter,
Defines(String),
Budget(usize),
Anchor(usize),
}
pub type Files = Vec<(String, String)>;
pub fn compose(host: Host, source: &[(&str, &str)]) -> Result<Files, ComposeError> {
let find = |path: &'static str| {
source
.iter()
.find(|(each, _)| *each == path)
.map(|(_, text)| *text)
.ok_or(ComposeError::Missing(path))
};
let (kept, skill_md, added) = match host {
Host::ClaudeCode => {
let skill_md = claude_skill_md(find("SKILL.md")?, find(FRAGMENT)?, find(ROUTE)?)?;
let reference = (
COMPOSED_REFERENCE.to_owned(),
find(HOST_REFERENCE)?.to_owned(),
);
(None, Some(skill_md), Some(reference))
}
Host::Codex => (Some(CODEX_ADAPTATION), None, None),
};
let mut files: Files = source
.iter()
.filter(|(path, _)| !path.starts_with("agents/") || Some(*path) == kept)
.map(|(path, text)| {
let text = match (&skill_md, *path) {
(Some(composed), "SKILL.md") => composed.clone(),
_ => (*text).to_owned(),
};
((*path).to_owned(), text)
})
.collect();
files.extend(added);
Ok(files)
}
fn claude_skill_md(skill_md: &str, fragment: &str, route: &str) -> Result<String, ComposeError> {
let lines: Vec<&str> = skill_md.split('\n').collect();
if lines.first() != Some(&"---") {
return Err(ComposeError::NoFrontmatter);
}
let close = lines[1..]
.iter()
.position(|line| *line == "---")
.ok_or(ComposeError::NoFrontmatter)?
+ 1;
let added = fields(fragment)?;
budget(&lines[1..close], &added)?;
let anchors: Vec<usize> = (close..lines.len())
.filter(|at| lines[*at].contains(ANCHOR))
.collect();
let [anchor] = anchors[..] else {
return Err(ComposeError::Anchor(anchors.len()));
};
let mut after = anchor + 1;
while lines.get(after).is_some_and(|line| line.starts_with(" ")) {
after += 1;
}
let mut composed: Vec<&str> = lines[..close].to_vec();
composed.extend(added.iter().copied());
composed.extend(&lines[close..after]);
composed.extend(route.trim_end_matches('\n').split('\n'));
composed.extend(&lines[after..]);
Ok(composed.join("\n"))
}
fn fields(fragment: &str) -> Result<Vec<&str>, ComposeError> {
let lines: Vec<&str> = fragment
.lines()
.filter(|line| !line.trim().is_empty() && !line.starts_with('#'))
.collect();
for line in &lines {
let field = line.split_once(':').map_or(*line, |(field, _)| field);
if OWNED.contains(&field) {
return Err(ComposeError::Defines(field.to_owned()));
}
}
Ok(lines)
}
fn budget(frontmatter: &[&str], added: &[&str]) -> Result<(), ComposeError> {
let value = |lines: &[&str], field: &str| {
let prefix = format!("{field}: ");
lines
.iter()
.find_map(|line| line.strip_prefix(&prefix))
.map_or(0, |value| value.chars().count())
};
let length = value(frontmatter, "description") + value(added, "when_to_use");
if length > LISTING_BUDGET {
return Err(ComposeError::Budget(length));
}
Ok(())
}
#[cfg(test)]
mod tests {
use super::{ComposeError, Host, compose};
const SKILL_MD: &str = "---\nname: x\ndescription: d\n---\n\n- Read `references/the-loop.md`\n first.\n- Read `references/b.md`.\n";
fn source(fragment: &'static str) -> Vec<(&'static str, &'static str)> {
vec![
("SKILL.md", SKILL_MD),
("agents/claude/claude-host.md", "host"),
("agents/claude/frontmatter.yaml", fragment),
(
"agents/claude/route.md",
"- Read `references/claude-host.md`.\n",
),
("agents/openai.yaml", "interface: {}"),
("agents/another/host.md", "another host"),
("references/the-loop.md", "loop"),
]
}
#[test]
fn the_claude_code_package_takes_the_fragment_the_route_and_the_host_reference() {
let files = compose(Host::ClaudeCode, &source("# note\nwhen_to_use: w\n")).unwrap();
let paths: Vec<&str> = files.iter().map(|(path, _)| path.as_str()).collect();
assert_eq!(
paths,
[
"SKILL.md",
"references/the-loop.md",
"references/claude-host.md"
]
);
assert_eq!(
files[0].1,
"---\nname: x\ndescription: d\nwhen_to_use: w\n---\n\n- Read `references/the-loop.md`\n first.\n- Read `references/claude-host.md`.\n- Read `references/b.md`.\n"
);
}
#[test]
fn the_codex_package_keeps_its_own_adaptation_alone() {
let files = compose(Host::Codex, &source("when_to_use: w\n")).unwrap();
let paths: Vec<&str> = files.iter().map(|(path, _)| path.as_str()).collect();
assert_eq!(
paths,
["SKILL.md", "agents/openai.yaml", "references/the-loop.md"]
);
assert_eq!(files[0].1, SKILL_MD);
}
#[test]
fn a_fragment_that_defines_name_or_description_is_refused() {
for (fragment, field) in [("name: y\n", "name"), ("description: y\n", "description")] {
assert_eq!(
compose(Host::ClaudeCode, &source(fragment)),
Err(ComposeError::Defines(field.to_owned()))
);
}
}
#[test]
fn a_listing_past_the_budget_is_refused() {
let long: &'static str = Box::leak(format!("when_to_use: {}\n", "w".repeat(1536)).into());
assert_eq!(
compose(Host::ClaudeCode, &source(long)),
Err(ComposeError::Budget(1537))
);
}
}