#!/usr/bin/env python3 # -*- coding: utf-8 -*- """Compare AGENTS.md directory structure with actual files.""" import os import re import sys REPO_ROOT = os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__)))) ISSUE_BODY_FILE = os.path.join(REPO_ROOT, ".github", "issue_body.md") def scan_files(directory, extensions): # type: (str, tuple) -> set """Scan directory for files with given extensions.""" result = set() base = os.path.join(REPO_ROOT, directory) if not os.path.isdir(base): return result for root, dirs, files in os.walk(base): dirs[:] = [d for d in dirs if not d.startswith(".") and d != "__pycache__"] for f in files: if not f.startswith(".") and f.endswith(extensions): result.add(os.path.relpath(os.path.join(root, f), REPO_ROOT).replace(os.sep, "/")) return result def parse_agents_md(): # type: () -> set """Extract file paths from AGENTS.md directory structure (Tab-indented).""" agents_file = os.path.join(REPO_ROOT, "AGENTS.md") if not os.path.exists(agents_file): print("Error: AGENTS.md not found") sys.exit(1) with open(agents_file, "r", encoding="utf-8") as f: content = f.read() match = re.search(r"### Directory Structure.*?```text\s*\n(.*?)```\s*", content, re.DOTALL) if not match: return set() files = set() stack = [] # type: list for line in match.group(1).split("\n"): if not line.strip(): continue depth = len(line) - len(line.lstrip("\t")) name = line.lstrip("\t").split(":")[0].strip() if not name or "*" in name or name == "...": continue stack = stack[:depth] if name.endswith("/"): stack.append(name.rstrip("/")) else: path = "/".join(stack + [name]) if path.startswith(("ddns/", "doc/", "schema/")) and not path.endswith((".png", ".svg", ".jpg", ".gif", ".ico")): files.add(path) return files def main(): # type: () -> None actual = ( scan_files("ddns", (".py")) | scan_files("doc", (".md",)) | scan_files("schema", (".json",)) ) documented = parse_agents_md() added, deleted = sorted(actual - documented), sorted(documented - actual) # Remove old issue body file if exists if os.path.exists(ISSUE_BODY_FILE): os.remove(ISSUE_BODY_FILE) if not added and not deleted: print("No changes detected") sys.exit(0) # Build and write issue body lines = ["AGENTS.md directory structure is out of sync.\n"] if added: lines.append("## New Files\n") lines.extend("- `%s`" % f for f in added) lines.append("") if deleted: lines.append("## Missing Files\n") lines.extend("- `%s`" % f for f in deleted) lines.append("") lines.append("## Required Updates\n1. Update directory structure\n2. Update version/date") lines.append("\n---\n*Auto-generated by update-agents workflow.*") with open(ISSUE_BODY_FILE, "w", encoding="utf-8") as f: f.write("\n".join(lines)) print("Changes detected: %d new, %d missing" % (len(added), len(deleted))) if __name__ == "__main__": main()