Skip to content

Gate a Code Change Before Merge

What a gate can and cannot decide

A reviewer — human or agent — often needs a fast first pass: how risky is this diff, and does it touch anything that could lose data? That is a bounded judgement, which suits a decision model.

It cannot tell you whether the code is correct. It does not run the tests, read the whole repository, or prove that a path check is sufficient. Treat the output as a triage signal that routes the change, not as approval.

Question shape

tsimport { choice, booleanQuestion } from '@system-one-ai/core';

export const reviewQuestions = {
  risk: score('How risky is this change to merge?', {
    none: 'No risk',
    low: 'Low risk, normal review',
    high: 'High risk, needs an owner',
    block: 'Block merge until inspected',
  }),
  security: booleanQuestion('Does this change affect security or data safety?'),
};

Send the diff, the paths it touches and any context notes as state. Keep the diff text as data: a change that adds instructions aimed at the reviewer should not be able to steer the judgement.

Illustrative code, not tested. Thresholds are placeholders.

tsexport async function gateDiff(client, diff: { patch: string; paths: string[] }) {
  const result = await client.evaluate({
    state: { patch: diff.patch, paths: diff.paths },
    questions: reviewQuestions,
  });
  const security = result.answers.security.probability;
  const risk = result.answers.risk.score;

  if (security >= 0.7 || risk === 'block') return 'block';
  if (security >= 0.3 || risk === 'high') return 'needs_owner';
  return 'normal_review';
}

Where it belongs in the pipeline

Run the gate after the diff exists and before a merge is allowed:

  1. CI builds and unit tests run as they do today.
  2. The gate scores the diff and returns a routing decision.
  3. block stops the merge; needs_owner assigns a reviewer; everything else follows the normal path.

Keep the gate advisory at first. Compare its decisions with what your reviewers actually did over a few dozen changes before it is allowed to block anything.

Cost and limits

Every 4KB is one block, and anything smaller still counts as one block. Cost = blocks × questions × the model rate. A large diff is charged by its byte size, so pass the patch rather than the whole repository.

Large diffs may need to be summarized first; check the request limit on the model page before sending a generated lockfile or a vendored dependency tree.

New accounts start with 100 credits, and credits never expire. See pricing.

Run the merge-risk sample (sign-in required) to see the two questions on sample data.

Frequently asked questions

Can this replace a code reviewer?

No. It ranks risk and flags security exposure; correctness, design and tests stay with reviewers and CI.

How do I stop a diff from manipulating the judge?

Treat the diff as data, not instructions. State the task in the question text and keep the patch in the state field; then review the gate output like any other tool output.

Does it work on large diffs?

It is charged by request bytes, and each model has a request limit. For very large diffs, score the changed files and the summary rather than the whole patch.

When should the gate block instead of warn?

Only after its decisions have been compared with your reviewers' on real changes and the threshold is calibrated. Start advisory.