From 66c764a67d17c9d811672c82e4bed8febbd2d2de Mon Sep 17 00:00:00 2001 From: Vinta Chen Date: Sun, 8 Nov 2026 22:04:43 +0800 Subject: [PATCH] fix: prune unstarred repos from Rejected Additions in star scan The star scan pruned unstarred repos from its untracked ledger but left their Rejected Additions lines in docs/audit-logs.md, so that list went stale after unstars. Co-Authored-By: Claude --- .claude/skills/scan-github-stars/SKILL.md | 2 +- .../scripts/scan_github_stars.py | 25 +++++++++++++++++-- website/tests/test_scan_github_stars.py | 9 +++++++ 3 files changed, 33 insertions(+), 3 deletions(-) diff --git a/.claude/skills/scan-github-stars/SKILL.md b/.claude/skills/scan-github-stars/SKILL.md index 8d101059..1f48fd67 100644 --- a/.claude/skills/scan-github-stars/SKILL.md +++ b/.claude/skills/scan-github-stars/SKILL.md @@ -10,7 +10,7 @@ A star scan turns the maintainer's GitHub stars into proposed additions. Every s ## 1. Scan -Run `uv run python .claude/skills/scan-github-stars/scripts/scan_github_stars.py`, adding `--full` when the argument is `full`. With no ledger yet, a plain run already covers every star. Print the drop and prune counts from stderr. Done when the candidate TSV is in hand. +Run `uv run python .claude/skills/scan-github-stars/scripts/scan_github_stars.py`, adding `--full` when the argument is `full`. With no ledger yet, a plain run already covers every star. Print the drop and prune counts from stderr. When it pruned Rejected Additions lines, commit `docs/audit-logs.md` on its own, since unlike the ledger it is tracked. Done when the candidate TSV is in hand. ## 2. Screen diff --git a/.claude/skills/scan-github-stars/scripts/scan_github_stars.py b/.claude/skills/scan-github-stars/scripts/scan_github_stars.py index 4627cd4a..877aed63 100644 --- a/.claude/skills/scan-github-stars/scripts/scan_github_stars.py +++ b/.claude/skills/scan-github-stars/scripts/scan_github_stars.py @@ -6,7 +6,8 @@ recomputed every run, so a repo that becomes active again resurfaces. An incremental run also drops stars already judged: model screen-outs in local/starred-scan.tsv and maintainer rejections under docs/audit-logs.md "Rejected Additions". `--full` keeps them and shows the earlier verdict in the -`prior` column. Ledger rows for repos no longer starred are pruned each run. +`prior` column. Ledger rows and Rejected Additions lines for repos no longer +starred are pruned each run. Prints survivors as TSV on stdout, drop and prune counts on stderr. """ @@ -93,6 +94,22 @@ def prune_ledger(starred: set[str]) -> int: return len(rows) - len(kept) +def prune_register(starred: set[str]) -> int: + """Drop Rejected Additions lines for repos no longer starred; `owner/*` patterns stay.""" + lines = REGISTER.read_text().splitlines(keepends=True) + start = lines.index("## Rejected Additions\n") + end = next((i for i in range(start + 1, len(lines)) if lines[i].startswith("## ")), len(lines)) + kept = [] + for line in lines[start:end]: + match = REJECTED_LINE_RE.match(line) + if match and not match.group(1).endswith("/*") and match.group(1).lower() not in starred: + continue + kept.append(line) + if len(kept) < end - start: + REGISTER.write_text("".join(lines[:start] + kept + lines[end:])) + return end - start - len(kept) + + def main() -> None: parser = argparse.ArgumentParser(description=__doc__, formatter_class=argparse.RawDescriptionHelpFormatter) parser.add_argument("--full", action="store_true", help="rejudge stars already screened out or rejected") @@ -104,7 +121,9 @@ def main() -> None: prior = prior_verdicts() stars: list[Star] = [json.loads(line) for line in gh("api", "--paginate", "user/starred?per_page=100", "--jq", ".[]").splitlines()] - pruned = prune_ledger({star["full_name"].lower() for star in stars}) + starred = {star["full_name"].lower() for star in stars} + pruned = prune_ledger(starred) + pruned_rejections = prune_register(starred) dropped = Counter() print("repo\tlanguage\tstars\tpushed\ttopics\tdescription\tprior") for star in stars: @@ -131,6 +150,8 @@ def main() -> None: print(f" dropped {count}: {reason}", file=sys.stderr) if pruned: print(f" pruned {pruned} ledger rows for repos no longer starred", file=sys.stderr) + if pruned_rejections: + print(f" pruned {pruned_rejections} Rejected Additions lines for repos no longer starred", file=sys.stderr) if __name__ == "__main__": diff --git a/website/tests/test_scan_github_stars.py b/website/tests/test_scan_github_stars.py index 0ab7641e..8cf5d250 100644 --- a/website/tests/test_scan_github_stars.py +++ b/website/tests/test_scan_github_stars.py @@ -122,6 +122,15 @@ def test_ledger_rows_keyed_by_github_url(scan): assert module.LEDGER.read_text() == kept +def test_unstarred_repos_are_pruned_from_rejected_additions(scan): + module, _, run = scan + kept = "## Rejected Additions\n- Example/Project -- 2026-10-16: kept\n- gone/* -- 2026-10-16: organization pattern\n" + module.REGISTER.write_text(kept + "- gone/repo -- 2026-10-16: unstarred\n\n## Last Audited\n") + + assert "pruned 1 Rejected Additions" in run("--full").err + assert module.REGISTER.read_text() == kept + "\n## Last Audited\n" + + def test_parking_keeps_other_exclusions(scan): module, star, run = scan now = datetime.now(UTC)