From 27aa1bf2fe7496070de48be93acea624738891ea Mon Sep 17 00:00:00 2001 From: ginnoir Date: Mon, 8 Jun 2026 05:02:34 -0500 Subject: [PATCH] fix(romhacks): only link library files that exist on disk MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit handoff.json lists files captured at routing time, but the extraction-cruft cleanup later removes files extracted out of a kept archive. The Caddy file_server can only serve real files (not archive interiors), so existence-filter the art + guide rel-paths against library// before embedding/linking them — dropping phantom entries that would 404. --- .../orchestrator/render_catalog_notes.py | 20 +++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) diff --git a/stacks/romhacks/orchestrator/render_catalog_notes.py b/stacks/romhacks/orchestrator/render_catalog_notes.py index a3b7b19..6c3d714 100644 --- a/stacks/romhacks/orchestrator/render_catalog_notes.py +++ b/stacks/romhacks/orchestrator/render_catalog_notes.py @@ -39,6 +39,17 @@ def load_handoff(slug): return {} +def on_disk(slug, rels): + """Keep only the rel paths that actually exist under library//. + + The handoff record lists files captured at routing time, but the + extraction-cruft cleanup later removes files extracted out of a kept + archive — so a guide can be in handoff.json yet gone from disk (and the + file_server can only serve real files, not archive interiors).""" + base = LIBRARY / slug + return [rel for rel in rels if (base / rel).exists()] + + def pick_guides(guides, artifact): """Filter the raw handoff guide list to linkable docs/spreadsheets/extras. @@ -152,10 +163,11 @@ def render(r): # Box art — embed from the internal Caddy file-server. Fall back to art # filenames in the metadata folder if the handoff record is missing them. ho = load_handoff(r["slug"]) - art = ho.get("art") or [] + art = on_disk(r["slug"], ho.get("art") or []) if not art and (META / r["slug"]).exists(): - art = sorted(p.name for p in (META / r["slug"]).glob("*") - if p.suffix.lower() in (".png", ".jpg", ".jpeg", ".webp", ".gif")) + cand = sorted(p.name for p in (META / r["slug"]).glob("*") + if p.suffix.lower() in (".png", ".jpg", ".jpeg", ".webp", ".gif")) + art = on_disk(r["slug"], cand) # only those also present in the served library for a in art: fm.append(f"![|320]({file_url(r['slug'], a)})") if art: @@ -171,7 +183,7 @@ def render(r): if links: fm += ["## Download", ""] + [f"- {l}" for l in links] + [""] # Guides / spreadsheets / extras — link each to the served file. - guides = pick_guides(ho.get("guides", []), r["artifact"]) + guides = pick_guides(on_disk(r["slug"], ho.get("guides", [])), r["artifact"]) if guides: fm += ["## Guides & extras", ""] for rel in guides[:MAX_GUIDES]: