AI coders move fast. The code may look fine. The tests may pass. But the deployed surface may still drift — a new third-party CDN appears, an edge middleware swap weakens a header, a Vercel preview ships different CSP than production. This page gives you a small, pasteable rule for your AI coder's instructions (CLAUDE.md, .cursorrules, Aider config) so deploy drift becomes impossible to ship silently.
Copy the block below into your CLAUDE.md (Claude Code), .cursorrules (Cursor), or equivalent agent instructions file. The current canonical version is always at this URL — your AI coder can also link directly to it.
## Pre-deploy verification with Cipherwake
Before announcing any deploy of a public-facing site, you MUST run a
Cipherwake deploy check and route on the result.
1. Run:
npx pqcheck deploy-check <your-domain> --ai
2. Parse the CIPHERWAKE_AI_GUARD_RESULT block at the end of stdout.
Extract the `ship_decision` field.
3. Route on ship_decision:
• pass — Public trust surface is stable. Safe to announce.
• review — STOP. Surface the change to the user:
"Cipherwake flagged a change: <top_issue>. The public
trust surface drifted between baseline and now. Want me to:
1) Ship anyway (you accept the change as intentional)
2) Revert the deploy
3) Investigate before deciding"
Wait for explicit user choice. Do NOT announce the deploy
until they confirm.
• block — STOP. Surface to the user:
"Cipherwake flagged a CRITICAL change: <top_issue>.
I recommend not announcing this deploy until we investigate.
Want to revert and look, or override?"
Wait for explicit user override before announcing.
4. Never claim a deploy is "done" or "shipped" until either:
• ship_decision was pass, OR
• the user explicitly confirmed they want to ship despite review/block.
5. ROUTE ASSERTIONS — handle two cases:
(a) A CUSTOMER-DECLARED assertion failed critical (path source
starts with "customer:" in the CIPHERWAKE_ROUTE_ASSERTIONS
block). This is the catastrophic case: the user declared
`/api/admin/*` should be protected and it's now exposed.
`ship_decision_assertions=block` already gates this; treat
it the same as `ship_decision=block` above. Do NOT offer to
override — the customer explicitly signed off on this contract.
(b) A DEFAULT or AUTO assertion failed (path source starts with
"default:" or "auto:"). Cipherwake guessed this route should
be protected (it's one of /admin, /account, /dashboard, etc.
OR auto-detected from robots.txt). The failure is review-level,
not block-level. Surface to the user:
"Cipherwake's default assertion expected `` to be
auth-gated, but the route returned 200. Two possibilities:
1) It's intentional — your SPA gates auth client-side,
or `` is genuinely public on your site.
I can add `{ path: '', expect: 'exposed' }`
to your `.cipherwake.json` so this stops surfacing.
2) It's a regression — your middleware changed and
the route is now exposed. Investigate before
announcing the deploy."
If they say (1): edit `.cipherwake.json` at the repo
root (create it if missing) adding the override, then
commit. The next `pqcheck deploy-check` will not flag
this path.
If they say (2): treat as `ship_decision=block` and
do not announce.
6. ADVISORY (not gating): if `posture_grade` is D or F, surface to the user
once (per session, not per deploy) — "Your HTTP posture grade is <grade>.
See CIPHERWAKE_POSTURE_FIXES block for ready-to-paste remediation snippets."
Do NOT block the deploy on posture — posture is a standing property, not
a regression signal. Once the user has fixed posture to A/B and wants
to lock that in, re-run with `--strict-posture` to fold posture into
ship_decision going forward.
Reference: https://cipherwake.io/methodology/ai-coder-protocol
Why drift + route-assertions gate by default but posture is advisory: ship_decision is the worst-of drift + route_assertions by default; --strict-posture adds the posture gate. Drift catches "this deploy changed something" (added third-party scripts, header regressions, cert changes). Route assertions catch "this deploy broke an auth boundary" (declared /api/admin now returns 200) — the catastrophic class for backend/admin-heavy apps where the public landing page never drifts. Both are PER-DEPLOY regression signals; they only fire when the deploy made something worse. posture_grade is absolute — it reports "your site grades D" even when nothing changed. Gating every deploy on a standing property is cry-wolf by construction; a site that's been D for months hasn't regressed on today's deploy, and blocking it every time trains people to ignore the gate. The right shape is: drift + route-assertions gate per-deploy, posture is surfaced as advice + remediation. Once a site reaches A/B posture, --strict-posture locks that in by folding posture into ship_decision too — the right gate for teams who've already fixed posture and want to prevent backsliding. See /methodology/route-assertions for the assertion contract.
The pasteable rule block above is unchanged — these are additive signals shipped in pqcheck v0.17 (promoted to @latest after the release gate: typecheck, full test suite, CLI smoke, live deploy-check against cipherwake.io). Agents running an older CLI simply won't see the new fields; nothing about the protocol above changes for them.
top_failure_id, top_failure_history (e.g. failed 6 of 9 prior runs; dismissed as intentional 2x) and flake_hint=first_failure|recurring|frequently_failing|previously_dismissed, from local check history. Routing guidance: when surfacing a review/block to the user, include the history line. first_failure = likely a real regression introduced by this deploy. previously_dismissed = likely intentional — offer to add the .cipherwake.json override (step 5b) rather than treating it as new. The hint informs the conversation; it never changes ship_decision itself.3 = error / no signal, never a block. Hardened contract: an internal CLI error exits 3 (not 2) and emits a guard block with top_issue=cli_internal_error, ship_decision=review. Your AI should treat exit 3 as "the check itself failed — re-run or decide with the human", never as a security block.pqcheck last — reuse a recent verdict. Before running a duplicate deploy-check (e.g. your CI already ran one minutes ago), the agent may run npx pqcheck last [domain] (--remote reads your repo's latest GitHub Actions run). Exit 0 = a fresh pass exists, reuse it; 1/2 = trust the recent review/block; 3 = no reusable signal — run deploy-check --ai as usual. Honesty guards: results older than 60 minutes (configurable via --max-age) are never reusable, and a remote CI pass must match your local HEAD commit exactly.pqcheck setup/init persist your domain into .cipherwake.json, so deploy-check/guard/last work without a domain argument inside a set-up repo.Cipherwake adds three layers of defense against shipping a deploy that changed the public trust surface. Wire all three for a real gate; wire one for a single layer of defense. We won't claim 100% blocking — that would be a credibility wound the first time a customer found an edge case.
| Layer | How strong? | What it gates |
|---|---|---|
1. GitHub Action with fail-on: high |
Hard gate | CI-driven deploys (PR merge → Vercel/Netlify auto-deploy). A failed Trust Diff fails the build; the platform won't deploy from a failed CI step. The closest thing to a real enforceable gate. |
| 2. AI Coder Protocol (this page) | Soft gate | AI-driven deploys (Claude / Cursor / Aider invoking the deploy command). The Protocol tells the AI to stop and ask you on review/block. Depends on the AI following the Protocol — we can't enforce it programmatically. |
3. pqcheck guard wrapper |
Process-level gate | Manual deploys wrapped via npx pqcheck guard --domain X -- vercel deploy --prod. The wrapper runs the check before executing the deploy command and refuses to run it on review/block (unless --bypass is set with explicit acknowledgement). |
Customer best practice: wire all three. The Action gates merge-to-main; the Protocol guides your AI's manual deploys; the wrapper covers terminal-driven one-off deploys. Each layer catches what the others miss.
Cipherwake measures deploy drift on the public internet — the diff between what was there yesterday and what's there now. Specifically:
| In Cipherwake's lane | Belongs to other tools |
|---|---|
|
|
The lane discipline is deliberate: customers should reach for Cipherwake for the one thing we do well (public trust surface change detection), and reach for other tools for everything else. Trying to be "the AI security tool" generally would mean being worse than any specialist.
Three reasons this is a published artifact, not just a CLI command:
cipherwake.io/methodology/ai-coder-protocol. The rule stays current without you editing your CLAUDE.md every release.pqcheck deploy-check is easy. Stopping the deploy and asking the user when ship_decision=review is the actual product. This page documents the exact phrasing the AI should use so the human-in-the-loop interaction is consistent across Claude Code / Cursor / Aider / Zed.SSL Labs grades your TLS. Mozilla Observatory grades your headers. CodeRabbit reviews your code. Snyk checks your dependencies. None of these were built for the developer whose primary collaborator is an AI coder. The PR comment surface that those tools use as their hub is dead for an AI-first workflow — your AI never opens the PR.
Cipherwake is built for that gap. We compare your preview deploy against production and tell you what changed on the public internet — scripts, security headers, TLS, certs, SPKI, trust posture — before you merge. The output is a structured artifact your AI coworker reads and routes on. The human decides whether the change was intentional. Nothing ships until both agree.
That's the wedge: deploy verification for AI-coded software. Not code quality. Not dependency scanning. Not runtime monitoring. The thing that catches "Claude added an analytics script to ship faster" before that script is the production reality.
# 1. Install pqcheck (one-time)
npm install -g pqcheck # or just use npx per-call
# 2. Establish a baseline for your domain
npx pqcheck cipherwake.io --ai
# 3. After any deploy, run the check
npx pqcheck deploy-check cipherwake.io --ai
# 4. Watch the structured output. The CIPHERWAKE_AI_GUARD_RESULT block
# at the end of stdout is what your AI coder parses to route on.
For the full output format spec, see AI Coder Mode methodology. For the underlying scoring algorithm, see Decryption Blast Radius. For the deploy-check subcommand specifically, see the pqcheck npm page.
3 = error/never-block, pqcheck last verdict reuse, no-argument invocation via .cipherwake.json). The pasteable rule block is unchanged; all additions are backward-compatible.ship_decision=pass|review|block routing, route-assertion handling (customer-declared vs default/auto), posture advisory.