diff --git a/CHANGELOG.md b/CHANGELOG.md
index f7cc36c..c458e97 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -114,6 +114,9 @@ All notable changes to this project will be documented in this file.
- Showed four Field Notes on the homepage (one featured plus three) so a new post no longer pushes an entry off the page.
### Fixed
+- Added the missing canonical and Open Graph URLs to the Real World Reasoning
+ Agent page so production metadata verification recognizes
+ `https://ryanbaumann.dev/real-world-reasoning-agent/` as its sole owner.
- Restored the Strava 3D Explorer, which stopped loading rides after the Content-Security-Policy shipped. Only the OAuth exchange and the photo proxy are same-origin `/api/strava/*` calls; the demo reads activities, activity detail, streams, and photo metadata straight from `https://www.strava.com/api/v3` in the browser, and the Maps allowlist has no Strava origin in `connect-src`, so every read was blocked and the app showed "Failed to fetch activities". The demo now gets its own policy, `"csp": "maps-strava"` in apps.json: the Maps policy plus the Strava API origin in `connect-src` and the two image hosts it loads without the proxy (the athlete avatar, and the placeholder photos in the signed-out demo tour) in `img-src`. The other Maps demos and the portfolio are unchanged and carry no Strava origin. Policies are now composed from directive maps instead of copy-pasted strings, so a per-app relaxation can only widen a directive the base policy already declares.
### Removed
diff --git a/LEARNINGS.md b/LEARNINGS.md
index 510a44d..b614ad7 100644
--- a/LEARNINGS.md
+++ b/LEARNINGS.md
@@ -418,6 +418,22 @@ Evidence: Social cards were regenerated with `ryanbaumann.dev`; Lab metadata now
Use next time: Treat a domain move as a dependency inventory, not a string replacement. Check generated text in images, absolute asset URLs, deployment health targets, OAuth origins, email senders, analytics, API referrers, and search ownership before changing DNS.
+## 2026-07-27 - Production smoke must reach metadata gates after config gates
+
+Context: Two deploys built and routed healthy Cloud Run revisions but stopped
+at the runtime-variable check because `GEMINI_API_KEY` was not attached. Once
+the existing secret was attached, the next production smoke exposed a missing
+canonical URL on the newly imported Real World Reasoning page.
+Learning: Runtime configuration and rendered metadata are separate deployment
+boundaries. Clear configuration blockers before calling a release verified,
+then run the complete production smoke against the service URL so later gates
+are not hidden behind an earlier failure.
+Evidence: Cloud Run revision `fieldwork-00099-c2z` serves with
+`GEMINI_API_KEY` attached, and `demos/real-world-reasoning-agent/index.html`
+now owns one canonical and matching Open Graph URL.
+Use next time: For a new hosted demo, verify required runtime variable names
+before the paid build and verify its canonical URL in built HTML before merge.
+
## 2026-07-27 - Compile the deployable graph once per CI event
Context: Pull-request CI built each app in its package job, rebuilt every app
diff --git a/demos/real-world-reasoning-agent/index.html b/demos/real-world-reasoning-agent/index.html
index 66594e1..d72e5a0 100644
--- a/demos/real-world-reasoning-agent/index.html
+++ b/demos/real-world-reasoning-agent/index.html
@@ -8,8 +8,10 @@
name="description"
content="Watch an agent perceive the real world, reason over live signals, and act — planning days, dispatching fleets, scoring sites, filming cities, shipping campaigns. Built on Gemini + Google Maps Platform. Fork it."
/>
+
+