basic BMAD setup

This commit is contained in:
Ebbe Baß
2026-10-15 08:57:23 +02:00
parent 44029127dc
commit 5e747654b9
438 changed files with 41818 additions and 0 deletions
@@ -0,0 +1,52 @@
"""A stand-in agent CLI for the runner tests: `fake_harness.py <prompt> <cwd>`.
Behaves like a harness enough to exercise the runners: reads the skills staged under
`.agents/skills` in the cwd, obeys a canary line when the prompt says "yes", writes an
artifact, prints a usage line, and exits non-zero when the prompt says "crash". It also
checks the clean room: HOME must sit inside the stage and the host secret must be absent.
"""
import json
import os
import re
import sys
from pathlib import Path
CANARY_RE = re.compile(r"token `([^`]+)`")
def main() -> int:
prompt, cwd = sys.argv[1], Path(sys.argv[2])
home = Path(os.environ.get("HOME", ""))
# run_evals puts HOME beside the cwd; run_triggers puts it inside the stage it runs from.
if home.resolve().parent not in (cwd.resolve().parent, cwd.resolve()):
print(f"HOME not inside the stage: {home}", file=sys.stderr)
return 4
if "HOST_SECRET" in os.environ:
print("host secret leaked", file=sys.stderr)
return 5
if "crash" in prompt:
print("boom", file=sys.stderr)
return 1
tokens = []
for skill_md in sorted(cwd.glob(".agents/skills/*/SKILL.md")):
m = CANARY_RE.search(skill_md.read_text(encoding="utf-8"))
if m:
tokens.append(m.group(1))
if "edit-me" in prompt:
skill_md.write_text("edited by the run\n", encoding="utf-8")
(cwd / "made.txt").write_text(prompt, encoding="utf-8")
(cwd / "where.txt").write_text(str(cwd.resolve()), encoding="utf-8")
(cwd / "env.json").write_text(
json.dumps({k: v for k, v in os.environ.items() if k in ("FORWARDED", "ABSENT", "FAKE_CONFIG_DIR")}),
encoding="utf-8",
)
(cwd / "login.txt").write_text(str((home / ".fake" / "auth.json").is_file()), encoding="utf-8")
reply = ("yes" in prompt and tokens and tokens[0] + " ") or ""
print(json.dumps({"type": "assistant", "message": {"content": [{"type": "text", "text": reply + "done"}]}}))
print(json.dumps({"type": "result", "usage": {"input_tokens": 10, "output_tokens": 5}}))
return 0
if __name__ == "__main__":
sys.exit(main())
@@ -0,0 +1,41 @@
"""aggregate_benchmark.py leaves incomplete runs out of the numbers."""
import json
import sys
import tempfile
import unittest
from pathlib import Path
SCRIPTS_DIR = Path(__file__).resolve().parents[1]
sys.path.insert(0, str(SCRIPTS_DIR))
from aggregate_benchmark import load_records, summarize_config # noqa: E402
class AggregateTest(unittest.TestCase):
def test_incomplete_runs_are_excluded_and_counted(self):
with tempfile.TemporaryDirectory() as tmp:
root = Path(tmp)
rows = [
("a", {"status": "ok", "elapsed_s": 10.0}),
("b", {"status": "ok", "elapsed_s": 12.0}),
("c", {"status": "timeout", "elapsed_s": 600.0}),
("d", {"status": "harness-missing", "elapsed_s": 0.01}),
]
for name, data in rows:
(root / name).mkdir()
(root / name / "timing.json").write_text(json.dumps(data))
records, excluded = load_records(root)
self.assertEqual(excluded, 2)
self.assertEqual(summarize_config(records)["metrics"]["elapsed_s"]["mean"], 11.0)
def test_records_without_status_count_as_complete(self):
with tempfile.TemporaryDirectory() as tmp:
f = Path(tmp) / "runs.json"
f.write_text(json.dumps({"runs": [{"elapsed_s": 1.0}, {"elapsed_s": 3.0}]}))
records, excluded = load_records(f)
self.assertEqual((len(records), excluded), (2, 0))
if __name__ == "__main__":
unittest.main()
@@ -0,0 +1,99 @@
"""convert_cases.py maps skill-creator evals.json to runner cases.json and back."""
import json
import subprocess
import sys
import tempfile
import unittest
from pathlib import Path
SCRIPT = Path(__file__).resolve().parents[1] / "convert_cases.py"
SKILL_CREATOR = {
"skill_name": "brief-writer",
"evals": [
{
"id": 1,
"prompt": "write a brief for InsuLens from memo.md",
"expected_output": "a brief.md naming InsuLens",
"files": ["evals/files/memo.md"],
"expectations": ["brief.md exists and names InsuLens", "no invented claims"],
},
{"id": 2, "prompt": "just say hi", "expected_output": "", "files": [], "expectations": []},
],
}
def run(*args: str) -> subprocess.CompletedProcess:
return subprocess.run([sys.executable, str(SCRIPT), *args], capture_output=True, text=True)
class ConvertCasesTest(unittest.TestCase):
def setUp(self):
self.tmp = Path(tempfile.mkdtemp())
self.evals = self.tmp / "my-skill" / "evals" / "evals.json"
self.evals.parent.mkdir(parents=True)
self.evals.write_text(json.dumps(SKILL_CREATOR), encoding="utf-8")
def test_to_runner(self):
proc = run(str(self.evals))
self.assertEqual(proc.returncode, 0, proc.stderr)
cases = json.loads(proc.stdout)
self.assertEqual(
cases[0],
{
"id": "1",
"input": "write a brief for InsuLens from memo.md",
"rubric": [
"brief.md exists and names InsuLens",
"no invented claims",
"output matches: a brief.md naming InsuLens",
],
"state_prefix": None,
"files": ["evals/files/memo.md"],
},
)
self.assertEqual(cases[1]["rubric"], [], "empty expected_output adds no rubric line")
self.assertEqual(cases[1]["id"], "2")
def test_output_flag_writes_file(self):
out = self.tmp / "out" / "cases.json"
proc = run(str(self.evals), "--output", str(out))
self.assertEqual(proc.returncode, 0, proc.stderr)
self.assertEqual(proc.stdout, "")
self.assertEqual(len(json.loads(out.read_text(encoding="utf-8"))), 2)
def test_round_trip(self):
cases_path = self.tmp / "my-skill" / "evals" / "cases.json"
run(str(self.evals), "--output", str(cases_path))
proc = run(str(cases_path), "--to", "skill-creator")
self.assertEqual(proc.returncode, 0, proc.stderr)
back = json.loads(proc.stdout)
self.assertEqual(back["skill_name"], "my-skill", "skill_name defaults to the folder above evals/")
self.assertEqual(back["evals"], SKILL_CREATOR["evals"])
def test_skill_name_flag_and_non_numeric_id(self):
cases_path = self.tmp / "cases.json"
cases_path.write_text(
json.dumps(
{"cases": [{"id": "create-1", "input": "x", "rubric": ["a"], "state_prefix": None, "files": []}]}
),
encoding="utf-8",
)
proc = run(str(cases_path), "--to", "skill-creator", "--skill-name", "named")
self.assertEqual(proc.returncode, 0, proc.stderr)
back = json.loads(proc.stdout)
self.assertEqual(back["skill_name"], "named")
self.assertEqual(back["evals"][0]["id"], "create-1")
self.assertEqual(back["evals"][0]["expected_output"], "")
def test_rejects_runner_input_toward_runner(self):
bad = self.tmp / "cases.json"
bad.write_text("[]", encoding="utf-8")
proc = run(str(bad))
self.assertEqual(proc.returncode, 2)
self.assertIn("evals", proc.stderr)
if __name__ == "__main__":
unittest.main()
@@ -0,0 +1,68 @@
"""The clean-room contract in eval_common.build_case_env, shared by both runners.
The eval result is only honest if nothing from the host shell leaks into the subprocess: exactly
PATH, a fresh HOME, and the harness's `env` table, where a value is set as given with "~" meaning
the fresh HOME and an empty value forwards the host's only when the host has it. Nothing else.
"""
import sys
import unittest
from pathlib import Path
SCRIPTS_DIR = Path(__file__).resolve().parents[1]
sys.path.insert(0, str(SCRIPTS_DIR))
from eval_common import PLATFORM_ENV, build_case_env, validate_harness # noqa: E402
HOST_ENV = {
"PATH": "/usr/bin:/bin",
"HOME": "/Users/host",
"MY_API_KEY": "sk-test-123",
"AWS_SECRET_ACCESS_KEY": "host-secret-must-not-leak",
"AGENT_CONFIG_DIR": "/Users/host/.agent",
"EXTRA_VAR": "extra",
}
HOME = Path("/tmp/eval-case/.home")
def keys(env: dict) -> set[str]:
return set(env) - set(PLATFORM_ENV) - {"USERPROFILE"}
class EnvIsolationTest(unittest.TestCase):
def test_set_forward_and_expand(self):
harness = {"env": {"MY_API_KEY": "", "AGENT_CONFIG_DIR": "~/.agent", "MODE": "quiet"}}
env = build_case_env(harness, HOME, HOST_ENV)
self.assertEqual(keys(env), {"PATH", "HOME", "AGENT_CONFIG_DIR", "MY_API_KEY", "MODE"})
self.assertEqual(env["PATH"], HOST_ENV["PATH"])
self.assertEqual(env["HOME"], str(HOME), "HOME must be the fresh case home")
self.assertEqual(env["AGENT_CONFIG_DIR"], str(HOME / ".agent"), "~ points into the fresh home, not the host's")
self.assertEqual(env["MY_API_KEY"], "sk-test-123", "an empty value forwards the host's")
self.assertEqual(env["MODE"], "quiet")
self.assertNotIn("AWS_SECRET_ACCESS_KEY", env, "host secrets leaked")
def test_forwarded_var_absent_when_host_lacks_it(self):
# An empty credential would override the CLI's own login; the key must be absent, never empty.
for host in ({}, {"MY_API_KEY": ""}):
env = build_case_env({"env": {"MY_API_KEY": ""}}, HOME, {"PATH": "/bin", **host})
self.assertNotIn("MY_API_KEY", env)
def test_no_harness_still_minimal(self):
self.assertEqual(keys(build_case_env(None, HOME, HOST_ENV)), {"PATH", "HOME"})
def test_validation(self):
good = {"command": ["x", "{prompt}"], "env": {"A": ""}, "home_files": []}
self.assertIs(validate_harness(good), good)
for bad in (
{"command": ["x"]},
{"command": "x {prompt}"},
{"command": ["x", "{prompt}"], "env": ["A"]},
{"command": ["x", "{prompt}"], "home_files": "a"},
):
with self.assertRaises(ValueError, msg=bad):
validate_harness(bad)
if __name__ == "__main__":
unittest.main()
@@ -0,0 +1,213 @@
"""run_evals.py against the fake harness: staging, containment, exit codes, run folders."""
import json
import os
import subprocess
import sys
import tempfile
import unittest
from pathlib import Path
SCRIPTS_DIR = Path(__file__).resolve().parents[1]
sys.path.insert(0, str(SCRIPTS_DIR))
import eval_common # noqa: E402
RUNNER = SCRIPTS_DIR / "run_evals.py"
FAKE = Path(__file__).resolve().parent / "fake_harness.py"
def write(path: Path, text: str) -> None:
path.parent.mkdir(parents=True, exist_ok=True)
path.write_text(text, encoding="utf-8")
def make_project(root: Path, command: list[str] | None = None) -> tuple[Path, Path, Path]:
"""A project with a skill, a cases file, a fixture and a harness file. Returns (skill, cases, harness)."""
skill = root / "skills" / "greet"
write(skill / "SKILL.md", "---\nname: greet\ndescription: Greets. Use when greeting.\n---\nSay hi.\n")
write(skill / "scripts" / "__pycache__" / "x.pyc", "")
write(root / "fixtures" / "notes.md", "fixture\n")
cases = root / "evals" / "cases.json"
write(
cases,
json.dumps(
[
{"id": "c1", "input": "yes hello", "rubric": ["says hi"], "files": ["fixtures/notes.md"]},
{"id": "../escape", "input": "hello", "rubric": ["x"]},
]
),
)
harness = root / "harness.json"
write(
harness,
json.dumps(
{
"command": command or [sys.executable, str(FAKE), "{prompt}", "{cwd}"],
"skill_dir": ".agents/skills",
"env": {"FAKE_CONFIG_DIR": "~/.fake", "FORWARDED": "", "ABSENT": ""},
"home_files": [".fake/auth.json"],
}
),
)
return skill, cases, harness
def run(*args: str, host_home: Path | None = None) -> subprocess.CompletedProcess:
"""Run the runner with a host secret set and, when given, a fake host home holding a login file."""
env = {**os.environ, "HOST_SECRET": "must-not-leak", "FORWARDED": "yes"}
env.pop("ABSENT", None)
if host_home is not None:
(host_home / ".fake").mkdir(parents=True, exist_ok=True)
(host_home / ".fake" / "auth.json").write_text("{}", encoding="utf-8")
env.update(HOME=str(host_home), USERPROFILE=str(host_home))
return subprocess.run([sys.executable, str(RUNNER), *args], capture_output=True, text=True, env=env)
class RunEvalsTest(unittest.TestCase):
def test_baseline_stages_a_copy_and_contains_the_run(self):
with tempfile.TemporaryDirectory() as tmp:
root = Path(tmp)
skill, cases, harness = make_project(root)
out = root / "out"
res = run(
"--cases", str(cases), "--skill-path", str(skill), "--output-dir", str(out),
"--mode", "baseline", "--project-root", str(root), "--harness", str(harness), "--quiet",
host_home=root / "host-home",
) # fmt: skip
self.assertEqual(res.returncode, 0, res.stderr)
summary = json.loads(res.stdout)
self.assertEqual(summary["executed"], 4)
run_dir = Path(summary["run_dir"])
staged = run_dir / "skill" / "c1" / "cwd" / ".agents" / "skills" / "greet"
self.assertTrue(staged.is_dir() and not staged.is_symlink(), "the skill is copied, not linked")
self.assertFalse((staged / "scripts" / "__pycache__").exists())
self.assertFalse((run_dir / "bare" / "c1" / "cwd" / ".agents").exists(), "bare config stages nothing")
self.assertEqual((run_dir / "skill" / "c1" / "cwd" / "fixtures" / "notes.md").read_text(), "fixture\n")
case = run_dir / "skill" / "c1"
self.assertTrue((case / "cwd" / "made.txt").is_file(), "the workspace comes back as cwd/")
self.assertFalse((case / "cwd" / ".git").exists())
where = Path((case / "cwd" / "where.txt").read_text())
self.assertNotIn(run_dir.resolve(), where.parents, "the run happened outside the project")
self.assertEqual((case / "cwd" / "login.txt").read_text(), "True", "home_files brought the login over")
seen = json.loads((case / "cwd" / "env.json").read_text())
self.assertEqual(seen["FORWARDED"], "yes", "an empty value forwards the host's")
self.assertNotIn("ABSENT", seen, "a var the host lacks is left out")
self.assertTrue(
seen["FAKE_CONFIG_DIR"].endswith(".fake") and Path(seen["FAKE_CONFIG_DIR"]).is_absolute(), "~ expands"
)
for name in ("prompt.txt", "transcript.jsonl", "stderr.txt", "timing.json", "case.json"):
self.assertTrue((case / name).is_file(), name)
# the id with `..` stays inside the run folder
self.assertTrue((run_dir / "skill" / "_escape").is_dir())
self.assertFalse((out / "escape").exists())
timing = json.loads((run_dir / "skill" / "c1" / "timing.json").read_text())
self.assertEqual(timing["status"], "ok")
self.assertEqual(timing["total_tokens"], 15)
self.assertTrue(timing["tokens_reported"])
run_json = json.loads((run_dir / "run.json").read_text())
self.assertEqual(run_json["command"][2], "{prompt}")
def test_edit_in_a_run_does_not_touch_the_source(self):
with tempfile.TemporaryDirectory() as tmp:
root = Path(tmp)
skill, cases, harness = make_project(root)
write(cases, json.dumps([{"id": "e", "input": "edit-me", "rubric": ["x"]}]))
res = run(
"--cases", str(cases), "--skill-path", str(skill), "--output-dir", str(root / "out"),
"--project-root", str(root), "--harness", str(harness), "--quiet",
) # fmt: skip
self.assertEqual(res.returncode, 0, res.stderr)
self.assertIn("name: greet", (skill / "SKILL.md").read_text())
def test_fixture_escaping_the_workspace_is_an_error(self):
with tempfile.TemporaryDirectory() as tmp:
root = Path(tmp)
skill, cases, harness = make_project(root)
write(root / "secret.txt", "s\n")
write(cases, json.dumps([{"id": "f", "input": "hello", "rubric": ["x"], "files": ["../../secret.txt"]}]))
out = root / "out"
res = run(
"--cases", str(cases), "--skill-path", str(skill), "--output-dir", str(out),
"--project-root", str(root / "evals" / "deep"), "--harness", str(harness), "--quiet",
) # fmt: skip
self.assertEqual(res.returncode, 1)
summary = json.loads(res.stdout)
self.assertEqual(summary["results"][0]["status"], "error")
self.assertIn("escapes", summary["results"][0]["reason"])
# nothing landed above the case's cwd
run_dir = Path(summary["run_dir"])
self.assertEqual(sorted(p.name for p in run_dir.iterdir()), ["execution-summary.json", "run.json", "skill"])
def test_failures_exit_nonzero(self):
with tempfile.TemporaryDirectory() as tmp:
root = Path(tmp)
skill, cases, harness = make_project(root)
write(cases, json.dumps([{"id": "k", "input": "crash", "rubric": ["x"]}]))
res = run(
"--cases", str(cases), "--skill-path", str(skill), "--output-dir", str(root / "out"),
"--project-root", str(root), "--harness", str(harness), "--quiet",
) # fmt: skip
self.assertEqual(res.returncode, 1)
self.assertEqual(json.loads(res.stdout)["failures"], 1)
def test_missing_command_exits_nonzero(self):
with tempfile.TemporaryDirectory() as tmp:
root = Path(tmp)
skill, cases, harness = make_project(root, command=["no-such-harness-xyz", "{prompt}"])
res = run(
"--cases", str(cases), "--skill-path", str(skill), "--output-dir", str(root / "out"),
"--project-root", str(root), "--harness", str(harness), "--quiet",
) # fmt: skip
self.assertEqual(res.returncode, 1)
self.assertEqual({r["status"] for r in json.loads(res.stdout)["results"]}, {"harness-missing"})
def test_no_harness_stages_only_and_exits_3(self):
with tempfile.TemporaryDirectory() as tmp:
root = Path(tmp)
skill, cases, _ = make_project(root)
res = run(
"--cases", str(cases), "--skill-path", str(skill), "--output-dir", str(root / "out"),
"--project-root", str(root), "--quiet",
) # fmt: skip
self.assertEqual(res.returncode, 3, res.stderr)
summary = json.loads(res.stdout)
self.assertEqual(summary["skipped"], 2)
self.assertIn("BMad is not set up", summary["harness"])
def test_invalid_harness_is_a_usage_error(self):
with tempfile.TemporaryDirectory() as tmp:
root = Path(tmp)
skill, cases, harness = make_project(root)
write(harness, json.dumps({"command": ["claude", "-p"]}))
res = run(
"--cases", str(cases), "--skill-path", str(skill), "--output-dir", str(root / "out"),
"--harness", str(harness), "--quiet",
) # fmt: skip
self.assertEqual(res.returncode, 2)
self.assertIn("{prompt}", res.stderr)
def test_run_folders_never_collide(self):
with tempfile.TemporaryDirectory() as tmp:
out = Path(tmp)
a_id, a_dir = eval_common.make_run_dir(out, "x")
b_id, b_dir = eval_common.make_run_dir(out, "x")
self.assertNotEqual(a_dir, b_dir)
self.assertTrue(a_dir.is_dir() and b_dir.is_dir())
self.assertTrue(b_id.startswith(a_id))
def test_contained_and_safe_name(self):
with tempfile.TemporaryDirectory() as tmp:
root = Path(tmp)
self.assertEqual(eval_common.contained(root, "a/b.txt"), (root / "a" / "b.txt").resolve())
with self.assertRaises(ValueError):
eval_common.contained(root, "../b.txt")
with self.assertRaises(ValueError):
eval_common.contained(root, "/etc/passwd")
self.assertEqual(eval_common.safe_name("../escape"), "_escape")
self.assertEqual(eval_common.safe_name(".."), "unnamed")
self.assertEqual(eval_common.safe_name("Case 1/B"), "Case_1_B")
if __name__ == "__main__":
unittest.main()
@@ -0,0 +1,127 @@
"""run_triggers.py against the fake harness: canary detection, unmeasured queries, exit codes."""
import json
import subprocess
import sys
import tempfile
import unittest
from pathlib import Path
SCRIPTS_DIR = Path(__file__).resolve().parents[1]
sys.path.insert(0, str(SCRIPTS_DIR))
from run_triggers import CANARY_PREFIX, detect_load, parse_skill_md, write_synthetic_skill # noqa: E402
RUNNER = SCRIPTS_DIR / "run_triggers.py"
FAKE = Path(__file__).resolve().parent / "fake_harness.py"
def write(path: Path, text: str) -> None:
path.parent.mkdir(parents=True, exist_ok=True)
path.write_text(text, encoding="utf-8")
class TriggerRunTest(unittest.TestCase):
def test_canary_scores_queries_and_leaves_failed_ones_unmeasured(self):
with tempfile.TemporaryDirectory() as tmp:
root = Path(tmp)
skill = root / "skills" / "greet"
write(
skill / "SKILL.md",
"---\nname: greet\ndescription: 'Greets the user''s friends. Use when greeting.'\n---\nSay hi.\n",
)
queries = root / "triggers.json"
write(
queries,
json.dumps(
[
{"query": "yes greet me", "should_trigger": True},
{"query": "no thanks", "should_trigger": False},
{"query": "yes but wrong", "should_trigger": False},
{"query": "crash", "should_trigger": False},
]
),
)
harness = root / "harness.json"
write(harness, json.dumps({"command": [sys.executable, str(FAKE), "{prompt}", "{cwd}"]}))
res = subprocess.run(
[sys.executable, str(RUNNER), "--skill-path", str(skill), "--queries", str(queries),
"--output-dir", str(root / "out"), "--harness", str(harness), "--runs-per-query", "2", "--quiet"],
capture_output=True, text=True,
) # fmt: skip
self.assertEqual(res.returncode, 1, res.stderr)
out = json.loads(res.stdout)
by_query = {r["query"]: r for r in out["results"]}
self.assertEqual(by_query["yes greet me"]["trigger_rate"], 1.0)
self.assertTrue(by_query["yes greet me"]["pass"])
self.assertEqual(by_query["no thanks"]["trigger_rate"], 0.0)
self.assertTrue(by_query["no thanks"]["pass"])
self.assertFalse(by_query["yes but wrong"]["pass"], "a should-not query that fired fails")
crashed = by_query["crash"]
self.assertIsNone(crashed["pass"], "a query with failed attempts is never a pass")
self.assertEqual(crashed["runs"], 0)
self.assertEqual(len(crashed["errors"]), 2)
self.assertEqual(out["summary"], {"total": 4, "passed": 2, "failed": 1, "unmeasured": 1})
self.assertEqual(
out["description"], "Greets the user's friends. Use when greeting.", "YAML quotes are removed"
)
attempt = root / "out" / out["run_id"] / "queries" / "q000-r0"
for name in ("prompt.txt", "transcript.jsonl", "stderr.txt", "timing.json"):
self.assertTrue((attempt / name).is_file(), name)
staged = list((attempt / "cwd" / ".agents" / "skills").glob("greet-trig-*/SKILL.md"))
self.assertEqual(len(staged), 1, "the workspace with the staged skill comes back")
self.assertIn("user's friends", staged[0].read_text())
self.assertEqual(json.loads((attempt / "timing.json").read_text())["loaded"], True)
def test_no_harness_exits_3(self):
with tempfile.TemporaryDirectory() as tmp:
root = Path(tmp)
skill = root / "greet"
write(skill / "SKILL.md", "---\nname: greet\ndescription: Greets.\n---\n")
queries = root / "triggers.json"
write(queries, json.dumps([{"query": "hi", "should_trigger": True}]))
res = subprocess.run(
[sys.executable, str(RUNNER), "--skill-path", str(skill), "--queries", str(queries),
"--output-dir", str(root / "out"), "--project-root", str(root), "--quiet"],
capture_output=True, text=True,
) # fmt: skip
self.assertEqual(res.returncode, 3, res.stderr)
self.assertEqual(json.loads(res.stdout)["summary"]["unmeasured"], 1)
class ParseSkillTest(unittest.TestCase):
def test_quoted_and_block_descriptions(self):
with tempfile.TemporaryDirectory() as tmp:
cases = {
"description: 'It''s quoted. Use when x.'\n": "It's quoted. Use when x.",
'description: "Say \\"hi\\". Use when x."\n': 'Say "hi". Use when x.',
"description: |\n Block one.\n Block two.\n": "Block one. Block two.",
"description: 'Spans\n two lines.'\n": "Spans two lines.",
"description: Plain. Use when x.\n": "Plain. Use when x.",
}
for frontmatter, expected in cases.items():
write(Path(tmp) / "SKILL.md", f"---\nname: s\n{frontmatter}---\nBody.\n")
self.assertEqual(parse_skill_md(Path(tmp)), ("s", expected), frontmatter)
class CanaryTest(unittest.TestCase):
def test_token_is_in_the_body_not_the_name_or_description(self):
with tempfile.TemporaryDirectory() as tmp:
token = CANARY_PREFIX + "abcd1234"
name = write_synthetic_skill(Path(tmp), "greet", "Greets people.\nUse when greeting.", token)
text = (Path(tmp) / name / "SKILL.md").read_text()
frontmatter = text.split("---")[1]
self.assertNotIn(token, frontmatter)
self.assertNotIn(token, name)
self.assertIn(f"token `{token}`", text)
self.assertIn(" Use when greeting.", frontmatter)
def test_detection_needs_the_token(self):
token = CANARY_PREFIX + "abcd1234"
listing = json.dumps({"type": "system", "skills": ["greet-trig-abcd1234", "other"]})
self.assertFalse(detect_load(listing, token), "a startup listing of skill names is not a load")
self.assertTrue(detect_load(listing + "\n" + json.dumps({"text": f"{token} hello"}), token))
if __name__ == "__main__":
unittest.main()