diff --git a/scripts/lint-agents.sh b/scripts/lint-agents.sh index 086b386c..4be7ebcb 100755 --- a/scripts/lint-agents.sh +++ b/scripts/lint-agents.sh @@ -96,6 +96,11 @@ lint_file() { errors=$((errors + 1)) return fi + if ! awk 'NR > 1 && $0 == "---" {found = 1; exit} END {exit !found}' "$file"; then + echo "ERROR $file: missing frontmatter closing ---" + errors=$((errors + 1)) + return + fi # Extract frontmatter (between first and second ---) local frontmatter diff --git a/scripts/test-convert-outputs.sh b/scripts/test-convert-outputs.sh index 5ecdd242..b546e480 100755 --- a/scripts/test-convert-outputs.sh +++ b/scripts/test-convert-outputs.sh @@ -174,9 +174,12 @@ def find_desc(obj): return None def frontmatter(text): - if not text.startswith("---"): raise ValueError("no frontmatter") - parts = text.split("\n---", 1) - return yaml.safe_load(parts[0][3:]) + lines = text.splitlines() + if not lines or lines[0] != "---": raise ValueError("no frontmatter") + for end in range(1, len(lines)): + if lines[end] == "---": + return yaml.safe_load("\n".join(lines[1:end])) + raise ValueError("missing frontmatter closing ---") def parsed_desc(path, fmt): text = open(path, encoding="utf-8").read() diff --git a/scripts/test-frontmatter-closing.sh b/scripts/test-frontmatter-closing.sh new file mode 100644 index 00000000..7017b5f4 --- /dev/null +++ b/scripts/test-frontmatter-closing.sh @@ -0,0 +1,37 @@ +#!/usr/bin/env bash +# An unclosed source frontmatter must not become a deployable empty persona. +set -euo pipefail + +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +FIXTURE="$(mktemp -d "${TMPDIR:-/tmp}/agency-frontmatter-closing.XXXXXX")" +trap 'rm -rf "$FIXTURE"' EXIT + +cat > "$FIXTURE/unclosed.md" <<'EOF' +--- +name: Broken Agent +description: This agent is missing its closing frontmatter fence +color: blue +# Identity +# Core Mission +# Critical Rules +EOF + +if bash "$SCRIPT_DIR/lint-agents.sh" "$FIXTURE/unclosed.md" > "$FIXTURE/invalid.log" 2>&1; then + echo "linter accepted an agent with no closing frontmatter fence" >&2 + exit 1 +fi +grep -Fq 'missing frontmatter closing ---' "$FIXTURE/invalid.log" + +cat > "$FIXTURE/valid.md" <<'EOF' +--- +name: Valid Agent +description: This agent has a closing frontmatter fence +color: blue +--- +## Identity +## Core Mission +## Critical Rules +EOF +bash "$SCRIPT_DIR/lint-agents.sh" "$FIXTURE/valid.md" > "$FIXTURE/valid.log" 2>&1 + +echo "PASS: unclosed frontmatter is rejected and a valid agent still passes"