diff --git a/.github/workflows/pages-smoke.yml b/.github/workflows/pages-smoke.yml
index 9aef67e..aefe593 100644
--- a/.github/workflows/pages-smoke.yml
+++ b/.github/workflows/pages-smoke.yml
@@ -18,3 +18,10 @@ jobs:
test -f video-engineer.html
grep -qi '
' index.html
! grep -R -n -E '^(<<<<<<<|=======|>>>>>>>)' index.html script-writing-machine.html video-engineer.html
+
+ - uses: actions/setup-node@v4
+ with:
+ node-version: '22'
+
+ - name: Validate public registry and embedded fallbacks
+ run: npm run check-manifest
diff --git a/CLAUDE.md b/CLAUDE.md
index e1b0927..6f48fdf 100644
--- a/CLAUDE.md
+++ b/CLAUDE.md
@@ -21,7 +21,7 @@ GitHub Pages org site for DaveHomeAssist. Contains the project hub (index.html),
## Manifest Sync
-`project-manifest.json` is the single source of truth for the project list. Both `private-hub.html` and `index.html` embed a `FALLBACK_MANIFEST` block so the hubs still render if the fetch fails. After editing `project-manifest.json`, run `npm run sync-manifest` to propagate changes to both hubs' embedded fallbacks. Never edit the `FALLBACK_MANIFEST` blocks directly.
+`project-manifest.json` is the single source of truth for the project list. `index.html`, `public-hub.html` and `private-hub.html` each embed a `FALLBACK_MANIFEST` block so the hubs still render if the fetch fails. After editing `project-manifest.json`, run `npm run sync-manifest` to propagate changes to every embedded fallback (the target list lives in `scripts/sync-manifest.mjs`; add any new hub page there). Never edit the `FALLBACK_MANIFEST` blocks directly. `node scripts/sync-manifest.mjs --check` reports drift without writing.
## Documentation Maintenance
@@ -36,7 +36,9 @@ GitHub Pages org site for DaveHomeAssist. Contains the project hub (index.html),
| 002 | P1 | resolved | Video engineer LinkedIn URL points to generic linkedin.com | Fixed: href updated to https://www.linkedin.com/in/daverobertson93/ |
| 003 | P2 | obsolete | Elysium nav links hidden on screens under 480px with no fallback | Elysium pages removed from repo; issue no longer applies |
| 004 | P2 | obsolete | Elysium back link uses inline onmouseover/onmouseout | Elysium pages removed from repo; issue no longer applies |
-| 005 | P2 | open | Video engineer page has no back link to main portfolio | Users cannot navigate back to the hub |
+| 005 | P2 | resolved | Video engineer page has no back link to main portfolio | Fixed 2026-07-11 in 93ca6c6: "Back to Portfolio" link added to video-engineer.html |
+| 009 | P0 | resolved | private-hub.html threw ReferenceError on load (loadManifest removed in e21df48) | Fixed 2026-09-10: loader, validateManifest and manifestError restored |
+| 010 | P1 | resolved | public-hub.html FALLBACK_MANIFEST was not covered by sync-manifest and drifted to the 2026-04-12 registry | Fixed 2026-09-10: added to sync targets, regenerated, drift check gates CI |
| 006 | P1 | resolved | Public manifest exposed 11 more private repo URLs plus localPath/runCommand values | Fixed 2026-07-03: blanked 10 private URLs, repointed BPMDelayCalc to public bpm-delay-calculator, cleared all localPath/runCommand |
| 007 | P2 | resolved | private-hub.html was indexable and listed in sitemap.xml | Fixed 2026-07-03: robots meta set to noindex,nofollow; removed from sitemap |
| 008 | P2 | resolved | index.html footer linked to missing archives/index-v1.html (live 404) | Fixed 2026-07-03: link removed |
diff --git a/package.json b/package.json
index cef3b51..68b926a 100644
--- a/package.json
+++ b/package.json
@@ -4,6 +4,8 @@
"type": "module",
"scripts": {
"validate-manifest": "node scripts/validate-public-manifest.mjs",
- "sync-manifest": "npm run validate-manifest && node scripts/sync-manifest.mjs"
+ "check-manifest": "npm run validate-manifest && node scripts/sync-manifest.mjs --check",
+ "sync-manifest": "npm run validate-manifest && node scripts/sync-manifest.mjs",
+ "test": "npm run check-manifest"
}
}
diff --git a/private-hub.html b/private-hub.html
index c9f9798..6b956fa 100644
--- a/private-hub.html
+++ b/private-hub.html
@@ -947,8 +947,8 @@ Project details