> ## Documentation Index
> Fetch the complete documentation index at: https://docs.surfacearea.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# Gate a pull request

> validateWorld pushes the pull request's own world source, dispatches a run config against it, waits for every run, gates on the score, and returns a comment-ready markdown summary.

`validateWorld` is push, dispatch, wait and gate as one call.

Validation runs the pull request's own world source. The push files the checkout as a version on the pull request's branch, the dispatch pins that version, and the platform resolves the branch back to its open pull request.

## Validate a checkout in one call

```typescript theme={null}
import { validateWorld } from "@withgateway/sdk/worlds";

const report = await validateWorld("./worlds/acme-billing", {
  slug: "acme-billing",
  runConfig: "pr-gate",
  minScore: 0.7,
  onProgress: (line) => console.log(line),
});

console.log(report.markdown);
process.exit(report.ok ? 0 : 1);
```

`onProgress` reports each step as it happens: the push, the resolved run config, and each run's status while it waits.

## Every option

The first argument is the directory holding the world source.

| Option | Type | Default | Meaning |
| - | - | - | - |
| `runConfig` | `string` | required | A run config's name or id; the name is the stable handle CI should use |
| `slug` | `string` | the `pyproject` name | Which world the checkout publishes as |
| `branch` | `string` | the detected branch | Overrides what `detectProvenance()` found |
| `minScore` | `number \| null` | `null` | The score every run must meet |
| `timeoutMinutes` | `number` | `45` | How long to wait on each run |
| `onProgress` | `(line: string) => void` | none | Progress lines |
| `options` | `WorldsClientOptions` | environment | Host and keys |

Without a `branch` and outside both a git checkout and GitHub Actions, the call throws rather than guessing which branch it is validating.

## What the gate actually checks

Three conditions, all of them required for `ok` to be true.

1. Every dispatch was accepted.
2. Every run reached a terminal `COMPLETED` status.
3. When `minScore` is set, every run's score meets it.

<Info>
  A run that completes with no score fails a score gate rather than passing it. Null means not scored, never zero.
</Info>

## The report

| Field | Type | What it is |
| - | - | - |
| `ok` | `boolean` | The verdict, and the process exit code you want |
| `slug` | `string` | The world that was pushed |
| `branch` | `string` | The branch it was pushed on |
| `versionId` | `string` | The version the runs were pinned to |
| `contentHash` | `string` | Exactly what ran |
| `runConfig` | `{ id, name }` | The resolved config |
| `runs` | `ValidatedRun[]` | One per model: `model`, `runId`, `report`, and `failure` |
| `markdown` | `string` | A pull request comment, ready to post |

Each `ValidatedRun.failure` is null when that run passes, and otherwise says why it did not: a dispatch error, a non-completed status, a missing score, or a score under the bar. `report` is the full [`RunReport`](/sdk-ts/worlds#the-runreport-shape), or null when the dispatch itself failed.

## The markdown is the comment

`report.markdown` is a finished summary: a pass or fail headline, the commit and content hash that ran, a table of models with scores and links to each run, and a table of per-scenario rewards. Scenario tables longer than twelve rows fold into a `<details>` block.

```typescript theme={null}
import { writeFileSync } from "node:fs";

writeFileSync(process.env.GITHUB_STEP_SUMMARY!, report.markdown);
```

Post it as a pull request comment with the `gh` CLI, or write it to `$GITHUB_STEP_SUMMARY` as above to get it on the job's own page.

## In GitHub Actions

Three secrets and one script. Branch, commit and actor are detected from the Actions environment, so nothing about provenance has to be configured.

```yaml filename=".github/workflows/world-validate.yml" theme={null}
name: validate-world

on:
  pull_request:
    paths: ["worlds/acme-billing/**"]

env:
  GATEWAY_HOST: ${{ secrets.GATEWAY_HOST }}
  GATEWAY_PUBLIC_KEY: ${{ secrets.GATEWAY_PUBLIC_KEY }}
  GATEWAY_SECRET_KEY: ${{ secrets.GATEWAY_SECRET_KEY }}

jobs:
  validate:
    runs-on: ubuntu-latest
    timeout-minutes: 60
    permissions:
      contents: read
      pull-requests: write
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-node@v4
        with:
          node-version: 22
      - run: npm install @withgateway/sdk
      - run: node scripts/validate-world.mjs
```

```javascript filename="scripts/validate-world.mjs" theme={null}
import { writeFileSync } from "node:fs";
import { validateWorld } from "@withgateway/sdk/worlds";

const report = await validateWorld("./worlds/acme-billing", {
  slug: "acme-billing",
  runConfig: "pr-gate",
  minScore: 0.7,
  onProgress: (line) => console.log(line),
});

if (process.env.GITHUB_STEP_SUMMARY) {
  writeFileSync(process.env.GITHUB_STEP_SUMMARY, report.markdown);
}

for (const run of report.runs) {
  if (run.failure) console.error(`${run.model}: ${run.failure}`);
}

process.exit(report.ok ? 0 : 1);
```

<Info>
  Content-hash deduplication means an unchanged tree files no new bundle. Validation resolves the branch tip and pushes on top of it, so a re-run replaces its own previous push instead of conflicting with it.
</Info>

## Which gate to reach for

| You changed | Use |
| - | - |
| The world's source, in this pull request | `validateWorld` on this page |
| Your agent, against a published world | [`runSessions`](/sdk-ts/run-sessions) with `failUnder` |
| Nothing; you want the world's own test suite | `gateway worlds test`, see [Run API worlds in CI](/worlds/ci) |

## Where to go next

* [Run API worlds in CI](/worlds/ci) for the terminal workflow and the world test suite.
* [Publish a world](/sdk-ts/hub) for the `push` that `validateWorld` calls.
* [Worlds](/sdk-ts/worlds) for run configs and the run report.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.