Introduce a GitHub Actions workflow that detects when a new PDF is uploaded to assets/images/uploads/ and creates a stub content page (in _reports/ or _policies/) linking to it. This closes a recurring workflow gap where PDFs are uploaded through the CMS but the corresponding page is never created — leaving documents invisible on the site.
Which requirements does this CIP address? REQ-0001 (editorial continuity — the site must reliably surface content the comms lead publishes).
Decap CMS handles media uploads and content creation as two separate operations. An editor can upload a PDF in the media library without ever creating the content page that links to it. The site then contains an orphaned PDF with no public URL.
This happened concretely on 2026-07-23: ai-cam-public-dialogue-report-2026.pdf was uploaded in commit 77fe0bf but no _reports/ entry was created. The report was invisible on the site until a developer noticed and created the page manually (commit 603d9c4). There is no indication this was the first occurrence, only the first caught.
The failure mode is silent — no build error, no warning, no broken link — which makes it hard for the comms lead to notice.
Editor uploads PDF via CMS media library
↓
PDF committed to assets/images/uploads/
↓
[gap: nothing else happens]
Editor separately creates a Report/Policy entry in CMS
↓
Content page committed to _reports/ or _policies/
↓
Page appears on site linking to PDF
The two steps are not connected. If the editor completes step 1 but not step 2, the PDF is silently orphaned.
A GitHub Actions workflow fires on push to main when files matching assets/images/uploads/*.pdf are added. It checks whether a corresponding content entry exists (by scanning _reports/ and _policies/ for any file containing a link to that PDF path). If none is found, it either:
Option A — Open a GitHub issue flagging the orphaned PDF, prompting a developer or editor to create the content page.
Option B — Commit a stub content page to a new branch and open a pull request, pre-populated with the PDF filename, date, and a placeholder title for the editor to complete.
Option C — Post a Slack/email notification to the communications team flagging the unlinked PDF.
Option B is most useful: it creates something actionable in the CMS (a draft report the editor can open and complete) rather than just an alert that may be missed. Option A is simpler to implement and a good interim step. Option C requires additional integration work.
The stub content page should be pre-populated with:
report_date from the PDF commit timestamplinks[0].link pointing to the uploaded PDF pathA PDF at assets/images/uploads/foo.pdf is considered linked if any file in _reports/ or _policies/ contains the string foo.pdf. The check is intentionally simple — a string match rather than YAML parsing — to avoid false negatives from complex frontmatter structures.
To make the automation reliable, PDFs intended for reports should follow a naming pattern. Enforcing this through the CMS is not practical (Decap does not constrain upload filenames), but documenting the convention and using it as a filter (e.g. only trigger on PDFs not in a known-asset list) reduces false positives from PDFs uploaded for other purposes (event agendas, etc.).
scripts/check-orphan-pdfs.py) — given the current state of _reports/ and _policies/, list any PDF in assets/images/uploads/ that has no corresponding link..github/workflows/orphan-pdf-check.yml) — triggers on push to main, runs the detection script, opens an issue if orphans are found (Option A, as the initial implementation).77fe0bf and confirm ai-cam-public-dialogue-report-2026.pdf is flagged.The workflow only runs on new pushes. Existing orphaned PDFs from before the workflow is introduced will not be flagged retroactively unless the detection script is run manually. A one-off audit run at implementation time is recommended.
77fe0bf (before the report page was added) and confirm the PDF is flagged.scripts/check-orphan-pdfs.py.github/workflows/orphan-pdf-check.yml77fe0bf (upload) and 603d9c4 (manual fix)