Rivalatch

Shared ship door for AI agents

Knock once.
Get a receipt.

Rivalatch is one shared door that AI coding agents knock on before a ship moves. The door lodges the job, runs checks in a sandbox on a bundle or a public git commit, and hands back a pass/fail receipt with repro.

Public marketing name: Rivalatch. Code, env, packages, and webhook headers still say VibeGate (VIBEGATE_*, vibegate-*, X-VibeGate-Signature-256).

  • Tools3 frozen
  • Door words202 · 200 · 409
  • pass_min0.85

One door, one contract

Product blurb. A shared acceptance gate for agent-callable smoke / DOM / screenshot checks.

What it is

Rivalatch is a shared acceptance gate for agent-callable smoke / DOM / screenshot checks. Calling agents knock with gate.run, poll gate.status, and read a terminal GateResult via gate.get_result — one door, not a sandbox product and not a CI marketplace.

Why it exists

Many rival agents, one frozen contract: Lodged → Recalled on the same key + payload; Occupied or Contested (HTTP 409) when the slot isn’t yours. Evidence composes to a clean pass/fail without inventing mid-floats.

How to call it

HTTPS MCP or HTTP REST on the live Ship host. Authenticate with an API key (X-Api-Key / VIBEGATE_API_KEY). Intentional share-sheet / deep-link knocks (MOBILE_KNOCKER.md) are for ship claims; this page is the public directory product blurb. There is no billing product and no marketplace crowning.

How to knock

Three frozen tools, over HTTP REST or MCP. Same body either way. Send your own key in X-Api-Key; never paste it into a page, ticket, or chat.

gate.run
POST /v1/gate/run

Knock. Lodged 202 for a new key, Recalled 200 for the same key and payload, 409 for the same key with a different payload.

gate.status
GET /v1/gate/status/{job_id}

{ job_id, state, updated_at } with state queued | running | succeeded | failed.

gate.get_result
GET /v1/gate/results/{job_id}

The receipt (GateResult) once terminal. Non-terminal returns 202 with the status body.

HTTP

REST · /v1/gate/*
HOST=https://vibegate-production.up.railway.app

# knock: a public github.com commit, smoke GET /
curl -sS -X POST $HOST/v1/gate/run \
  -H "Content-Type: application/json" \
  -H "X-Api-Key: <your key>" \
  -d '{
    "app_ref": { "type": "git",
      "uri": "https://github.com/<owner>/<repo>",
      "rev": "<40-hex sha>" },
    "checks": ["smoke"],
    "acceptance": { "criteria": [], "base_url_path": "/" },
    "idempotency_key": "<uuid>"
  }'
# → 202 Lodged { job_id, state }

# then status and the receipt
curl -sS -H "X-Api-Key: <your key>" \
  $HOST/v1/gate/status/<job_id>
curl -sS -H "X-Api-Key: <your key>" \
  $HOST/v1/gate/results/<job_id>

app_ref.type is git (https, github.com, public repos; depth-1 clone at rev, static serve, no repo code executed) or bundle.

MCP

HTTPS /mcp · stdio
# HTTPS MCP: JSON-RPC, same dispatch as stdio
curl -sS -X POST $HOST/mcp \
  -H "Content-Type: application/json" \
  -H "X-Api-Key: <your key>" \
  -d '{"jsonrpc": "2.0", "id": 1,
       "method": "tools/call",
       "params": { "name": "gate.run",
         "arguments": { …same body… } } }'

# then, with { "job_id": "<job_id>" }
gate.status      # poll
gate.get_result  # the receipt

# stdio MCP for local agents
# (Cursor · Claude Code · Codex · Grok Build)
vibegate-mcp
# env: VIBEGATE_API_KEY=<your key>

No fourth tool. Install cards: MCP.md · agent card: AGENT.md.

Receipt anatomy

The terminal GateResult from gate.get_result. Closed shape: no fields beyond these.

Example receipt

example · not a live job
{
  "job_id": "job-20261007T195500Z-3f9a1c2e",
  "verdict": "pass",
  "noul_acceptance_met": 1.0,
  "thresholds": { "pass_min": 0.85 },
  "checks": [
    { "id": "smoke-5b1d07e2", "kind": "smoke",
      "status": "pass",
      "detail": "GET http://…/ → 200 in 41.2ms" }
  ],
  "repro": {
    "sandbox_id": "mock-5e0c9a1b2d3f",
    "commands": ["sandbox.create()",
      "sandbox.provision({…})", "GET …/",
      "sandbox.destroy(…)"],
    "screenshot_uris": [],
    "dom_snapshot_uri": null,
    "logs_uri": "…/job.log",
    "har_uri": null
  },
  "fail_class": null
}
  • job_idThe job the door lodged. Same key and payload recalls this same id.
  • verdictpass or fail. Terminal only.
  • noul_acceptance_metSet by the Spec/Jev path. With empty criteria it composes to 0.0 or 1.0 only; never an invented mid-float.
  • thresholds.pass_minMinimum noul_acceptance_met for pass. Empty-criteria code compose always reports 0.85. Only field in thresholds.
  • checksEach check: id, kind (smoke | e2e | visual | dom | log), status (pass | fail | error), detail.
  • reprosandbox_id, commands, screenshot_uris, dom_snapshot_uri, logs_uri, har_uri. Smoke-only knocks leave screenshots empty and the DOM snapshot null.
  • fail_classnull on pass. Else one of build, runtime, assert, visual_reg, timeout, infra.

Door words

Each door state has one glyph and one color. The shape alone is enough, so it reads in grayscale too. Wire codes are unchanged; the words are prose.

202lodged

Lodged

New idempotency key. The door takes the job and returns { job_id, state }.

running

Running

Checks run in the sandbox. gate.status reports queued or running until terminal.

pass

Pass

Receipt sealed with verdict: pass. fail_class is null.

fail

Fail

Receipt with verdict: fail and a class saying why, with repro to replay it.

fail_class: assert · build · infra …
200recalled

Recalled

Same key, same payload. The existing job comes back. No second ship.

409occupied · contested

Occupied / Contested

Same key, different payload. The 409 detail shows held (Occupied) vs incoming (Contested).

Used by Qoresence

Every push to Qoresence’s main gets a receipt.

every push · a receipt

Qoresence knocks on each push to main.

An opt-in workflow in ConWan30/Qoresence lodges the frozen gate.run body at the pushed commit. The door shallow-clones the public repo at that SHA, serves its Pages root, and smokes GET /.

The job_id, verdict, and fail_class land in the workflow’s job summary.

  1. Push to main.
  2. Knock: app_ref { type: git, uri: https://github.com/ConWan30/Qoresence, rev: <pushed sha> }, checks [smoke].
  3. Door: depth-1 clone at the SHA, static serve, smoke GET /.
  4. Receipt: verdict and fail_class in the job summary.

Live host

https://vibegate-production.up.railway.app

Public listing URLs (this host)

Operator

Contravious Battle / ConWan30

Questions, deletion, or access requests: Support. Agent docs: AGENT.md · MCP.md · MOBILE_KNOCKER.md.