carlos / movement Public

X-Carlos-Version is not proof; /api/version is

The first deploy of the HEAD fix reported "live", carried the new sha in
its header, and served the previous commit. The header is injected by the
edge from what it believes it promoted; /api/version is answered by the
process actually running, and after a promote those two disagree exactly
when it matters.

Caught only because the bug the deploy was meant to fix was still there:
HEAD kept returning 405 against a host claiming to run the fix. Without a
visible symptom it would have read as a clean deploy.

carlos restart, then poll /api/version until it flips. AGENTS.md now says
so, and says not to take carlos deploy's own word for it either.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Paul Campbell bcb33fed8243ea163ab45eb973d9e7bd0fb3f0ed parent 3a5bf5a
1 file changed, +14 −3
  • AGENTS.md +14 −3
diff --git a/AGENTS.md b/AGENTS.md
index 940ad55..f1c432f 100644
--- a/AGENTS.md
+++ b/AGENTS.md
@@ -79,9 +79,20 @@ and never in the primary checkout.
Any one of the three missing means it does not merge.
Review happens on a **deployed canary, never localhost**. A 200 is not a
-deploy verification — only `X-Carlos-Version` on the canonical host, after the
-watch, is proof. And a promote is not a deploy: until the process cycles, the
-old binary is still serving.
+deploy verification. And a promote is not a deploy: until the process cycles,
+the old binary is still serving.
+
+**`X-Carlos-Version` is not proof either — `GET /api/version` is.** Learned
+here on 2026-09-02. The header is injected by the edge from the version it
+believes it promoted; `/api/version` is answered by the process actually
+running. They disagree exactly when it matters: after a promote the header
+flips immediately while the old binary keeps serving, and `carlos deploy`
+reports "live" on the strength of the header. The deploy that taught us this
+looked green and was serving code from the previous commit.
+
+So: verify with `curl -s https://<host>/api/version` and compare it to the sha
+you built. If it lags, `carlos restart --app <a>` and poll that endpoint until
+it flips. Never take the header, and never take `carlos deploy`'s own word.
---