Inspiration
AI can now write a working change in minutes. It can also write one that passes every unit test and still violates what the human actually approved. A normal pipeline checks whether the code works. Nothing checks whether it still does what was asked.
We wanted GitLab to answer one more question on every merge request and every release: "Does the software still do what the human approved?"
What it does
A human writes a requirement: "Customers can refund their own orders under $100." IntentLock turns it into an Intent Contract, a short YAML file of checkable clauses (ownership, amount limit, auditability, …). A human approves it and its content hash is locked.
Then the demo plays out on real GitLab pipelines:
- BLOCKED. MR !4 adds an "instant approval for small refunds" fast path. The unit tests pass. IntentLock starts the app, exercises it against the contract, and finds that customer C001 can refund order O2001, which belongs to C002. The gate returns BLOCKED (job 17085872779).
- Duo remediates, a human starts it. A human starts the GitLab Duo remediation flow on the blocked MR. Duo reads the failing job and its log, diagnoses that the fast path skips the ownership check, and commits the fix plus the exact regression CI printed (commit a560b8fd, agent session 9289882).
- FIXED. CI re-verifies deterministically. The regression replays as
before=VIOLATED after=SATISFIEDand the gate returns FIXED (job 17086019433). - Release. After merge, the main pipeline (2934556743) issues a hashed Change Passport, deploys one image to staging and to a zero-traffic canary (both 5/5 SATISFIED), waits for a human to approve production, and promotes the same image digest. Nothing is rebuilt.
- INTENT HELD. A scheduled monitor re-checks production every 6 hours. Pipeline 2934574227: 5/5 SATISFIED, INTENT HELD.
A requirement change is also caught: MR !3 tries to raise the limit and is BLOCKED on AMOUNT_LIMIT (job 17081869940).
The model proposes. Deterministic evidence decides.
How we built it
- Intent Contract + verifier (Python,
python -m intentlock). It runs the FastAPI demo service and checks each clause with real HTTP calls. No LLM is in the verdict path. - Regression replay. A violation is saved as
regressions/REG-xxx.yamland replayed at the old commit (must be VIOLATED) and at the MR head (must be SATISFIED). - GitLab CI for merge requests, main/release and a schedule: JUnit and Code Quality
reports, exposed artifacts, protected environments, a manual production job, and a pipeline
schedule (
0 */6 * * *). - GitLab Duo Agent Platform, three custom flows in the AI Catalog:
- drift remediation (used on !4 and, in an earlier version, on !2: commit bb9450be)
- MR intent triage (posts one advisory note on request: sessions 9287235, 9287373 on !1)
- intent extraction (published; not run live: the demo contract was written by a human)
CI prints the evidence between markers in the job log; the flow reads it with
get_pipeline_failing_jobs / get_job_logs and commits with create_commit.
No long-lived GitLab token is used.
- Change Passport. One JSON record per MR and per release: contract hash, commit, verdict,
per-clause results, report hashes, image digest, environments, and an
integrityhash. - Google Cloud (see below). 74 pytest tests in the repository.
Challenges we ran into
- Keeping the LLM out of the verdict. Duo diagnoses and proposes; only the deterministic replay can turn BLOCKED into FIXED.
- Getting evidence to Duo without a long-lived token: CI prints the regression in the job log and the flow reads it through its own tools.
- Promoting a verified build instead of rebuilding it: production moves traffic to the already-verified canary revision, pinned by digest.
- Cloud Run reserves
/healthz, so the monitor cannot read the service version.
Accomplishments that we're proud of
- A full BLOCKED → FIXED → INTENT HELD loop on real GitLab pipelines and a live Cloud Run service, with every step traceable to a job ID.
- A Duo-authored fix that was only accepted after a deterministic replay proved it.
- A Change Passport that ties what was approved, what was verified and which image went live.
What we learned
Tests describe how code behaves; an intent contract describes what a human agreed to. Making that agreement executable, hashed and replayable turns "the AI changed something" into a reviewable, auditable event. Supervised autonomy works best when the human approves the outcome and the evidence, not every keystroke.
What's next for IntentLock
- More clause types beyond ownership and amount limits, and more than one service.
- Running the extraction flow live so contracts can be drafted from issues, still approved by a human.
- A SAST job and a dedicated runtime service account.
- Posting the Change Passport as a release asset and reading the version in the monitor.
GitLab Duo usage and supervised autonomy
A human approves the contract, starts each Duo flow, merges, and approves the production job. Duo reads the failing job, diagnoses the problem, and commits the fix and the regression. Nothing triggers Duo automatically, and Duo never decides a verdict or approves a release.
Google Cloud
Cloud Run (refund-staging; refund-prod with a tagged 0%-traffic canary), Cloud Build and
Artifact Registry (one image, pinned by digest), Workload Identity Federation from GitLab
id_tokens (no long-lived service-account key), and Secret Manager for the monitor token.
The same image digest moves through staging, canary and production. Deployment code is in
deployment/ and ci/ in the public repo, and the production service is public:
https://refund-prod-jvom7un37a-uc.a.run.app/docs
Honest limitations
- One demo service and one contract.
- The extraction flow is published but was not run live; the demo contract was written and approved by a human.
- Duo is started by a human, by design.
- The !4 drift diff was written by hand for the demo; Duo wrote the fix and the regression.
- The contract's
source_issuefield says#1while the requirement is issue #2. The contract was approved before the issue was re-filed, and the field is hash-locked, so we did not rewrite it. /passport.jsonon production is the pre-release passport; the release passport is thepassport:releaseartifact (job 17086689833).- The monitor's version field shows
?(Cloud Run reserves/healthz); it is cosmetic. - There is no SAST job; the MR !4 pipeline as a whole was not all green.
Path and autonomy
Path: Start Fresh. IntentLock was built from scratch for this hackathon. The repository history starts on 2026-10-09. The app, the CI/CD and the Duo automation are all new, and it is deployed on Google Cloud Run.
Autonomy: Supervised. A human starts the Duo flow. Duo executes the remediation workflow (reads the failing job, diagnoses, commits the fix and the regression). Deterministic CI decides the result. A human approves production.
Log in or sign up for Devpost to join the conversation.