#!/usr/bin/env bash set -euo pipefail usage() { cat < Validate that an agent pair's sources provenance chain is complete and internally consistent. Operates at plugin scope only — exits 0 silently for project and user scope agents. Arguments: agent-file Path to either the Claude Code .md or Copilot .agent.md agent file. Exit codes: 0 All checks passed (or nothing to validate, or not plugin scope) 1 One or more checks failed Checks performed: 0 source_keys present in agent pair but agents/sources.md absent 1 FILL IN: placeholders in agents/sources.md 2 source_keys in agent files → slug exists in agents/sources.md 3 Contributing files listed in agents/sources.md exist on disk (plugin-root relative) 4 Contributing files back-reference the parent slug in their source_keys 5 Research doc field present and not placeholder EOF } if [[ "${1:-}" == "--help" || "${1:-}" == "-h" ]]; then usage exit 0 fi if [[ $# -lt 1 ]]; then echo "Error: agent-file is required." >&2 echo "" >&2 usage >&2 exit 1 fi python3 -u - "$1" <<'PYTHON' import sys import os import re agent_file = os.path.abspath(sys.argv[1]) fname = os.path.basename(agent_file) agent_dir = os.path.dirname(agent_file) # --- Detect provider --- if fname.endswith('.agent.md'): provider = 'copilot' name_stem = fname[:-len('.agent.md')] elif fname.endswith('.md'): provider = 'claude-code' name_stem = fname[:-len('.md')] else: print(f"Error: unrecognized extension '{fname}' — expected .md or .agent.md", file=sys.stderr) sys.exit(2) # --- Find plugin root --- def find_plugin_root(start_dir): current = os.path.abspath(start_dir) while True: if (os.path.isfile(os.path.join(current, 'plugin.json')) or os.path.isfile(os.path.join(current, '.claude-plugin', 'plugin.json'))): return current parent = os.path.dirname(current) if parent == current: return None current = parent plugin_root = find_plugin_root(agent_dir) if plugin_root is None: sys.exit(0) # --- Derive counterpart --- if provider == 'copilot': counterpart = os.path.join(agent_dir, name_stem + '.md') else: counterpart = os.path.join(agent_dir, name_stem + '.agent.md') sources_md_path = os.path.join(plugin_root, 'agents', 'sources.md') # --- Helpers --- PLACEHOLDER_RE = re.compile(r'(?' to the '## {slug}' entry in agents/sources.md." ) elif rd_value == "" or PLACEHOLDER_RE.search(rd_value): emit_fail( "Research doc field is empty or placeholder", f"agents/sources.md (## {slug})", f"The '## {slug}' entry has an unfilled Research doc value.", "Set '- **Research doc:**' to a real path relative to repo root, or '(none)' if not applicable." ) print_findings() sys.exit(1 if has_fail else 0) PYTHON