GATEPROOF: I'M A HARNESS MAKER, NOT THE HARNESS

Three concepts: Gate, Act, Assert.

TECHNICAL GUIDE 2026.01.17

WHY THIS EXISTS

I'm not building features anymore. I'm building harnesses.

When you run AI agents in loops, you hit the same wall every time: observation. You need to see what changed, why it changed, what failed, and what reality says. Without observation, loops turn into superstition.

Gateproof is a collection of ideas for doing this end-to-end. It's what I'm using in my other projects. Not expecting many people to use it—it's just the patterns I've collected.

gateproof.dev — github.com/acoyfellow/gateproof

THE THREE CONCEPTS

Gate

Run a verification. Returns pass/fail.

Act

Do something. Deploy. Hit an endpoint. Run a command.

Assert

Check the logs. Did it work? Did it fail? What evidence exists?

That's it. Minimal surface area. Maximum power.

WHEN TO USE IT

Use gateproof when you need to:

  • Observe what changed after an action
  • Validate against constraints (gates)
  • Assert results from observability backends
  • Run E2E tests that check logs, not just HTTP responses

It's not a testing framework. It's a harness. It connects actions to observations to assertions. You plug in your own observability backend.

Works with Cloudflare Analytics Engine, Workers Logs API, or any backend you implement. The backend interface is tiny.

WHY I USE IT

I'm a harness maker now. Not the harness.

When I build features, I don't write the tests. I write the gates. I don't implement the feature. I verify it works. I don't debug the code. I examine what the observability backend saw.

Gateproof makes this explicit. Three concepts. Plug in your backend. Run gates. Check assertions. Done.

It's the pattern I keep reaching for across projects. So I collected it into one place. Not a library. Just ideas. Use what you need.

THE PATTERN

import { Gate, Act, Assert } from "gateproof";
import { CloudflareProvider } from "gateproof/cloudflare";

const provider = CloudflareProvider({
  accountId: process.env.CLOUDFLARE_ACCOUNT_ID!,
  apiToken: process.env.CLOUDFLARE_API_TOKEN!
});

const result = await Gate.run({
  observe: provider.observe({ 
    backend: "analytics", 
    dataset: "worker_logs" 
  }),
  act: [
    Act.browser({ url: "https://my-worker.workers.dev" })
  ],
  assert: [
    Assert.noErrors(),
    Assert.hasAction("request_received")
  ]
});

if (result.status !== "success") process.exit(1);

Observe logs. Run an action. Assert results. That's the loop.

THE INVERSION

Old: I write code, tests validate it.
New: I write gates, actions trigger them, assertions verify reality.

Old: I am the harness.
New: Gateproof is the harness. I observe.

Old: Debugging means tracing my code.
New: Debugging means examining what the observability backend saw.

Same features. Built backwards. The harness stays. The code changes.

PLUG YOUR BACKEND

Gateproof works with any observability backend. Just implement the interface:

interface Backend {
  start(): Effect.Effect<LogStream, ObservabilityError>;
  stop(): Effect.Effect<void, ObservabilityError>;
}

See the patterns directory for examples: Cloudflare Analytics Engine, Workers Logs API, CLI streams, custom backends.

NOT A LIBRARY

Gateproof isn't trying to be a world-saving library. It's a collection of ideas I keep using. Three concepts. Minimal surface area. Maximum power.

If you need this pattern, use it. If you don't, don't. I'm not expecting many people to use it. It's just what works for me.

The harness stays. The code changes. I'm a harness maker, not the harness.

I don't build features. I build gates. I don't implement. I verify.

Three concepts: Gate, Act, Assert. That's the pattern.