Files
playbook/antigravity-awesome-skills/skills/lore/scripts/find_stale.py
T
2026-07-13 07:44:54 +00:00

117 lines
3.1 KiB
Python

#!/usr/bin/env python3
"""Find stale entries in .lore/.
Usage:
python find_stale.py # default: 90-day threshold
python find_stale.py --days=180
python find_stale.py --json
Reports two categories:
Stale : entry has not been `#verified` within the threshold
(or has no #verified at all, and was added > threshold
days ago).
Pending arch : entry already carries a `#stale:` tag and is waiting
to be moved into .lore/archive/.
Output is plain text by default, JSON with --json.
Used by:
- `audit` workflow (read-only)
- `compress` workflow (advisory)
- `lore mirror` (sanity check before regenerating)
"""
import json
import subprocess
import sys
from datetime import date, datetime, timedelta
from pathlib import Path
def get_entries():
script = Path(__file__).parent / "list_entries.py"
r = subprocess.run(
[sys.executable, str(script), "--json"],
capture_output=True,
text=True,
)
if r.returncode != 0:
print(r.stderr.strip(), file=sys.stderr)
sys.exit(1)
try:
return json.loads(r.stdout)
except json.JSONDecodeError as exc:
print(f"error: list_entries.py returned invalid JSON: {exc}",
file=sys.stderr)
sys.exit(1)
def parse_date(s: str):
try:
return datetime.strptime(s, "%Y-%m-%d").date()
except (ValueError, TypeError):
return None
def main():
days = 90
json_output = "--json" in sys.argv[1:]
for arg in sys.argv[1:]:
if arg.startswith("--days="):
days = int(arg.split("=", 1)[1])
today = date.today()
cutoff = today - timedelta(days=days)
entries = get_entries()
stale = []
pending_arch = []
for e in entries:
# Already marked stale → pending archive
if "stale" in e["tags"]:
pending_arch.append(e)
continue
# Determine the entry's freshness date
last_v = parse_date(e["last_verified"])
added = parse_date(e["tags"].get("added"))
ref_date = last_v or added
if ref_date is None:
continue # no date info, can't decide
if ref_date < cutoff:
stale.append(e)
if json_output:
out = {
"threshold_days": days,
"as_of": today.isoformat(),
"stale": stale,
"pending_archive": pending_arch,
}
print(json.dumps(out, indent=2, ensure_ascii=False))
return
print(f"=== Stale (unverified > {days} days, as of {today}) ===")
if not stale:
print(" (none)")
for e in stale:
ref = e["last_verified"] or e["tags"].get("added", "unknown")
print(f" [{e['file']}] {e['id']} {e['text']}")
print(f" ref date: {ref}")
print()
print("=== Pending archive (tagged #stale) ===")
if not pending_arch:
print(" (none)")
for e in pending_arch:
print(f" [{e['file']}] {e['id']} {e['text']}")
print(f" marked stale: {e['tags']['stale']}")
if __name__ == "__main__":
main()