mirror of
https://github.com/Shubhamsaboo/awesome-llm-apps.git
synced 2026-08-28 19:11:53 +08:00
Fix project-graveyard --redact corrupting state and faking relapse verdicts
--redact overwrote name/path in place, so --state persisted '(redacted)' paths (destroying the real data Necromancer mode greps) and the relapse-watch map, keyed on the redacted path, reported on-disk repos as 'no longer found on disk'. --json also leaked real unversioned names/paths under --redact. Keep real_name/real_path when redacting; use them for relapse matching and the local --state file (a resume artifact, always real); keep the shareable console and --json fully redacted (unversioned included) and exclude real_* from the JSON dead payload. All four skill-evals CI jobs still pass. Fixes #1025
This commit is contained in:
@@ -390,6 +390,11 @@ def main(argv=None):
|
||||
|
||||
if args.redact:
|
||||
for i, r in enumerate(sorted(repos, key=lambda r: r["first"]), 1):
|
||||
# Keep the real identifiers so relapse-watch matching and the local
|
||||
# --state resume file stay correct; only the shareable report is
|
||||
# redacted (see by_path / --state / --json below).
|
||||
r["real_name"] = r["name"]
|
||||
r["real_path"] = r["path"]
|
||||
r["name"] = "project-%d" % i
|
||||
r["path"] = "(redacted)"
|
||||
|
||||
@@ -482,7 +487,7 @@ def main(argv=None):
|
||||
|
||||
# ---- relapse watch: hold past resurrections to their promise ----
|
||||
if state["resurrections"]:
|
||||
by_path = {r["path"]: r for r in repos}
|
||||
by_path = {r.get("real_path", r["path"]): r for r in repos}
|
||||
lines = []
|
||||
for res in state["resurrections"]:
|
||||
r = by_path.get(res["path"])
|
||||
@@ -519,19 +524,26 @@ def main(argv=None):
|
||||
"days_threshold": args.days,
|
||||
"alive": [{k: r[k] for k in ("name", "path", "last", "commits")} for r in alive],
|
||||
"finished": [{k: r[k] for k in ("name", "path", "last", "commits")} for r in finished],
|
||||
"unversioned": [{"name": u.name, "path": str(u)} for u in unversioned],
|
||||
"dead": [{k: r[k] for k in r if k not in ("messages", "gaps", "last_touched")}
|
||||
"unversioned": [{"name": "unversioned-%d" % i, "path": "(redacted)"}
|
||||
if args.redact else {"name": u.name, "path": str(u)}
|
||||
for i, u in enumerate(unversioned, 1)],
|
||||
"dead": [{k: r[k] for k in r
|
||||
if k not in ("messages", "gaps", "last_touched", "real_name", "real_path")}
|
||||
for r in dead]}, f, indent=1)
|
||||
print("full report: %s" % args.json)
|
||||
|
||||
if args.state:
|
||||
# The state file is a local resume artifact, not the shared report, so it
|
||||
# always records the real names/paths even under --redact.
|
||||
state["last_scan"] = {
|
||||
"date": datetime.now().strftime("%Y-%m-%d"),
|
||||
"roots": [str(r) for r in roots],
|
||||
"dead": [{"name": r["name"], "path": r["path"], "cause": r["causes"][0][0],
|
||||
"pulse": r["pulse"]} for r in dead],
|
||||
"alive": [{"name": r["name"], "path": r["path"]} for r in alive],
|
||||
"finished": [{"name": r["name"], "path": r["path"]} for r in finished],
|
||||
"dead": [{"name": r.get("real_name", r["name"]), "path": r.get("real_path", r["path"]),
|
||||
"cause": r["causes"][0][0], "pulse": r["pulse"]} for r in dead],
|
||||
"alive": [{"name": r.get("real_name", r["name"]), "path": r.get("real_path", r["path"])}
|
||||
for r in alive],
|
||||
"finished": [{"name": r.get("real_name", r["name"]), "path": r.get("real_path", r["path"])}
|
||||
for r in finished],
|
||||
"unversioned": [{"name": u.name, "path": str(u)} for u in unversioned],
|
||||
}
|
||||
with open(args.state, "w") as f:
|
||||
|
||||
Reference in New Issue
Block a user