Download plugins/agent-overwrite-grader/scripts/agent_overwrite_grader/grade.py from memento-team/claude-plugins: direct link, hf CLI and curl.
- Browser
- Download file 3.52 kB
-
https://huggingface.co/memento-team/claude-plugins/resolve/main/plugins/agent-overwrite-grader/scripts/agent_overwrite_grader/grade.py
- Command line
-
hf download hf://memento-team/claude-plugins/plugins/agent-overwrite-grader/scripts/agent_overwrite_grader/grade.py
-
curl -L -o grade.py https://huggingface.co/memento-team/claude-plugins/resolve/main/plugins/agent-overwrite-grader/scripts/agent_overwrite_grader/grade.py
3.52 kB
| """The grading rule: which files two sessions wrote within an hour, read from a git log. | |
| A line-for-line port of the web grader's grade.js; a shared fixture test keeps the two verdicts equal. | |
| """ | |
| import math | |
| import re | |
| from datetime import datetime | |
| COMMAND = "git log --all --source --name-only --since='1 month ago' --format='%H|%an|%aI|%S'" | |
| WINDOW_MIN = 60 | |
| HEAD = re.compile(r"^[0-9a-f]{7,64}\|") | |
| def branch(ref): | |
| """A ref as git prints it (%S, or %D's decorations) to a branch name; "" when the commit carries none.""" | |
| names = [s.strip() for s in (ref or "").split(",")] | |
| names = [re.sub(r"^HEAD -> ", "", s) for s in names] | |
| names = [s for s in names if s and s != "HEAD" and not s.startswith("tag: ") and not s.startswith("refs/tags/")] | |
| if not names: | |
| return "" | |
| return re.sub(r"^refs/remotes/[^/]+/", "", re.sub(r"^refs/heads/", "", names[0])) | |
| def millis(text): | |
| """An ISO 8601 date with its offset to epoch milliseconds; None when it does not read as one.""" | |
| try: | |
| when = datetime.fromisoformat(text.strip().replace("Z", "+00:00")) | |
| except ValueError: | |
| return None | |
| return int(round(when.timestamp() * 1000)) | |
| def parse(text): | |
| commits, cur = [], None | |
| for line in re.split(r"\r?\n", str(text or "")): | |
| if HEAD.match(line): | |
| p = line.split("|") | |
| when = millis(p[-2]) if len(p) >= 4 else None | |
| if when is not None: | |
| cur = {"hash": p[0], "author": "|".join(p[1:-2]), "when": when, "ref": branch(p[-1]), "files": []} | |
| commits.append(cur) | |
| continue | |
| f = line.strip() | |
| if cur is not None and f: | |
| cur["files"].append(f) | |
| return commits | |
| def two_sessions(a, b): | |
| """Two commits are two sessions when their authors differ, or both carry a branch and the branches differ.""" | |
| return a["author"] != b["author"] or bool(a["ref"] and b["ref"] and a["ref"] != b["ref"]) | |
| def grade(text): | |
| commits, by_file = parse(text), {} | |
| for c in commits: | |
| for f in c["files"]: | |
| by_file.setdefault(f, []).append(c) | |
| files = [] | |
| for name, writes in by_file.items(): | |
| writes = sorted(writes, key=lambda c: c["when"]) | |
| pairs, latest = [], 0 | |
| for i in range(1, len(writes)): | |
| j = i - 1 | |
| while j >= 0 and writes[i]["when"] - writes[j]["when"] <= WINDOW_MIN * 60000: | |
| if two_sessions(writes[i], writes[j]): | |
| minutes = int(math.floor((writes[i]["when"] - writes[j]["when"]) / 60000 + 0.5)) | |
| pairs.append({"a": writes[j], "b": writes[i], "minutes": minutes}) | |
| latest = max(latest, writes[i]["when"]) | |
| j -= 1 | |
| if pairs: | |
| pairs.sort(key=lambda p: p["minutes"]) | |
| files.append({"file": name, "count": len(pairs), "latest": latest, "pairs": pairs[:3]}) | |
| files.sort(key=lambda f: (-f["count"], -f["latest"], f["file"])) | |
| times = [c["when"] for c in commits] | |
| days = max(1, math.ceil((max(times) - min(times)) / 864e5)) if times else 0 | |
| sessions = {(c["author"], c["ref"]) for c in commits} | |
| return {"commits": len(commits), "sessions": len(sessions), "days": days, "files": files} | |
| def score_line(report): | |
| n = len(report["files"]) | |
| head = "No file" if n == 0 else "1 file" if n == 1 else "%d files" % n | |
| return "%s written by two sessions within an hour, in %d %s of history." % ( | |
| head, report["days"], "day" if report["days"] == 1 else "days") | |