Turning Ota Contracts into Merge-Gate Truth
How Ota turns contract-owned verification lanes into stable merge-check identities, CI drift findings, and an opt-in GitHub pull-request gate.
Overview
Most repositories already have a merge gate.
The problem is that its truth usually lives inside provider configuration:
- a GitHub Actions workflow
- a GitLab pipeline
- a branch-protection check name
- a shell command copied into several jobs
- a convention that reviewers are expected to remember
That makes CI look authoritative while quietly creating a second operating model beside the repository itself.
The repo says one thing. The workflow says another. Both can remain internally valid while drifting apart.
Ota takes a stricter position: the repository contract should own what must be verified. The CI provider should own when and where that verification runs.
That separation lets Ota turn a declared verification workflow into machine-readable merge-gate truth without pretending it owns GitHub, GitLab, branch protection, secrets, runners, or deployment policy.
The Two-Sources-of-Truth Problem
Imagine a repository where ota.yaml declares verify as the canonical CI lane, but the GitHub workflow still runs an older command.
Both files parse. The workflow may even stay green.
But the repository now has two answers to a basic governance question:
What must pass before this change is trusted?
That drift commonly appears as:
- a contract adds a required verification lane but CI never runs it
- CI changes a verification command without updating the contract
- a workflow hardcodes a different Ota version or installation source
- a renamed job silently changes the status context used by branch protection
- one operating-system lane keeps running while another disappears
Waiting for a cryptic CI failure is too late. The contract-to-provider relationship should be inspectable before merge.
The Contract Owns The Verification Lane
The starting point is a reviewed Ota workflow with explicit CI intent:
version: 1project: name: api tasks: verify: description: Run the canonical verification lane safe_for_agent: true command: exe: npm args: [test] workflows: default: verify verify: intent: ci_verification run: task: verify agent: safe_tasks: [verify] bootstrap: ota: source: kind: version version: v1.6.24This contract establishes several pieces of governance truth:
verifyis a declared task, not an arbitrary workflow shell string- the workflow has merge-relevant
ci_verificationintent - the selected lane is available to the enforced agent execution boundary
- CI bootstrap can consume the same contract-owned Ota source
The contract does not declare pull_request, ubuntu-latest, repository secrets, deployment environments, or notification behavior. Those remain provider-owned concerns.
Ota Projects Stable Merge Identity
Run:
ota doctor --jsonWhen the contract declares merge-relevant verification truth, Doctor can publish:
governance.required_verification_lanes[]governance.merge_gate
An abridged record looks like this:
{
"governance": {
"required_verification_lanes": [
{
"merge_check_id": "ota.verify.verify",
"lane_task": "verify",
"lane_kind": "task",
"contract_sources": ["workflows.verify.run.task"]
}
],
"merge_gate": {
"state": "projected",
"blocking": false,
"required_lane_count": 1,
"drift_lane_count": 0,
"decision_basis": [
{
"id": "projection:ota.verify.verify",
"family": "required_lane",
"evidence_class": "derived",
"detail": "verify"
}
],
"replay": {
"status": "satisfied"
}
}
}
}The important field is merge_check_id.
It is Ota's stable identity for the required verification lane. Provider check names and workflow file layout can change without forcing downstream consumers to infer lane identity from display text.
The verdict also carries its basis and replay posture. A merge decision should not be an unexplained boolean.
projected Does Not Mean Provider-Enforced
This is an important honesty boundary.
state: projected means Ota has derived the required lane from contract truth. It does not mean:
- GitHub branch protection requires that check
- every provider workflow is aligned
- the provider executed the lane successfully
- deployment policy was satisfied
Ota must not claim provider enforcement merely because it knows what the contract requires.
When Ota establishes a mismatch between the contract and recovered CI workflow truth, the state can become drift_detected. The corresponding lane becomes blocking and cites the drift basis.
That distinction keeps three layers separate:
- contract projection: what the repo requires
- provider wiring: how CI currently invokes verification
- merge enforcement: what the provider or organization actually requires before merge
Turn Drift Into A Pull-Request Gate
Structured output is useful, but teams should not have to remember to run the comparison manually.
The Ota GitHub Action supports an opt-in drift gate:
name: Contract-to-CI drift on: pull_request: permissions: contents: read jobs: contract-ci-drift: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - name: Enforce contract-to-CI alignment uses: ota-run/action@v1 with: command: doctor source: contract fail-on-ci-drift: true comment-pr: falsefail-on-ci-drift is deliberately opt-in. With command: doctor, it fails when Ota establishes contract-owned CI bootstrap or verification drift through the canonical merge-gate and drift findings.
It does not turn every ordinary Doctor warning into CI drift.
For stricter supply-chain reproducibility, pin third-party Actions to reviewed immutable revisions under your organization's dependency policy. The example uses the public major channel for readability.
A Live Deliberately Failing Example
Kylrix PR #1 demonstrates the boundary directly.
Its normal verification lanes are green:
- Ubuntu native SQLite verification
- macOS native SQLite verification
- Windows native SQLite verification
- Ubuntu container verification
The dedicated Contract-to-CI drift gate is intentionally red.
The pull request reproduces a realistic governance failure: workflow-owned Ota bootstrap truth duplicates and diverges from the contract instead of consuming agent.bootstrap.ota.source.
That result is more useful than making the whole matrix red. It proves that application verification can succeed while the repository's execution-governance wiring has still drifted.
The gate names the governance problem instead of disguising it as an unrelated test failure.
What Ota Should Own
Ota should own:
- the canonical verification task and workflow
- stable merge-lane identity
- contract-to-CI drift evaluation
- machine-readable blocking and decision basis
- contract-owned bootstrap source
- receipts and proof expectations attached to the selected lane
The CI provider should continue to own:
- event triggers and schedules
- permissions and credentials
- runner labels and infrastructure
- environments and deployment approvals
- provider-specific notifications
- unrelated build, release, and delivery jobs
This is not Ota trying to become another CI language. It is Ota making the execution-governance slice portable and explicit.
What The Gate Still Does Not Prove
A green contract-to-CI drift gate does not prove the whole repository is ready.
It does not prove:
- that branch protection is configured correctly
- that the required provider job actually ran on every relevant event
- that runtime proof established every application invariant
- that secrets, deployments, and external systems are healthy
- that a maintainer's contract claim is correct merely because it is internally consistent
Those are separate governance and proof questions.
The value of the merge gate is narrower and concrete: it prevents CI verification and bootstrap truth from silently diverging from the repository contract where Ota has enough evidence to establish that drift.
Start With One Required Lane
The smallest useful adoption path is:
- Declare one canonical workflow with
intent: ci_verification. - Run
ota doctor --jsonand inspectrequired_verification_lanesandmerge_gate. - Reconcile any established workflow drift.
- Add the dedicated
fail-on-ci-driftpull-request check. - Make that named check required through your provider's branch-protection policy.
That final provider configuration matters. Ota emits the governance truth and the check result; GitHub or another merge chokepoint decides whether contributors can route around it.
Use the public references for the exact shipped behavior:
The Broader Point
A repository contract becomes valuable at merge time when it stops being another file reviewers are expected to remember.
Ota turns declared verification truth into stable lane identity, compares it with recoverable CI wiring, and emits a machine-readable verdict that a mandatory provider check can enforce.
The contract is the specification. The merge gate is one enforcement point. Keeping those roles separate is how Ota centralizes governance without creating another source of CI truth.
Take action