Your bug.
Fixed for you
first.
Diagram: the ring, drawn in characters, with eight stations in order: report, evidence, fix for one, stop drill, verified for them, told, everyone, flag removed. One lit cell, marked with an at sign, is you, the person who reported the bug. It moves from station to station. At “everyone” the rest of the ring lights up as the flag reaches 25% and then 100% of users.
8 stations From the report to the flag removed
Each station is described below, with what it leaves in GitLab.
When a customer reports a bug, the fix goes live for that customer first, behind a GitLab feature flag switched on for them. It is checked on their own requests in production, they are told, and only then does everyone get it and the flag is removed.
The ticket does not close on a merge. It closes when production shows the reporter’s requests working.
- Hands-off: the customer’s report is the only human act.
- Built on Kutt, the open-source URL shortener, running on Google Cloud.
- The customers are synthetic. A person writes their reports from real mailboxes.
How one ring runs
Eight stations, one customer report. Every station leaves something in GitLab that you can open and check.
-
Report
A customer writes to support on the app’s Contact support page. The conductor files it as an issue and adds the customer to it by email, so every reply reaches their inbox. This is the only human act in the ring.
Leaves in GitLab
- Issue, with the customer as an email participant
-
Evidence
The conductor finds the customer’s account and posts their failing requests from production traces. The intake agent compares them with the report. A matching failure means reproduced. No failure in production means the ring asks the customer one question and writes no code.
Leaves in GitLab
- Evidence note
ring::state on the issue board- Issue weight
-
Fix for one
- Write
- The fix agent writes a regression test that replays the customer’s failing request, and a fix behind the feature flag
ring-<issue>that keeps the old code path. - Check
- Unit tests, the customer’s regression test, the negative control and the charter check, with SAST, secret detection, dependency, IaC and container scanning. Duo Code Review reads every merge request.
- Ship
- The merge request merges itself when every gate passes. One signed image goes to staging, a smoke test, then production: the same digest.
- Switch on
- The flag is switched on for one user list: the reporter, plus the ring’s own probe account.
Leaves in GitLab
- Branch and merge request
- Pipeline and test report
- Vulnerability report
- Container image, CycloneDX SBOM, Sigstore signature
- Staging and production environments
- Release with notes and evidence
- Feature flag and its user list
-
Stop drill
Before anyone relies on the flag, the ring proves it works as an off switch. It replays the customer’s request in production as its probe account with the flag off, then on, and needs the old behaviour, then the fixed one.
Leaves in GitLab
- Drill note on the issue
- Flag history
-
Verified for them
The conductor reads the reporter’s own requests on the flagged path from GitLab Observability. Enough successes and no failures: verified. A failure: the flag goes off, an incident opens, and the ring tries again with the new evidence.
Leaves in GitLab
- Observability traces of the reporter’s requests
- Incident, when they still fail
-
Told
The reply agent drafts the message to the customer. A gate checks the draft for anything that must not leave the building, then the conductor posts it on the issue, and GitLab emails it to the customer.
Leaves in GitLab
- Reply on the issue, emailed to the customer
-
Everyone
The flag ramps to 25% of users, then 100%. It holds at each step while the fleet’s error rate stays under 1%.
Leaves in GitLab
- Flag strategy changes in the flag history
-
Flag removed
A merge request removes the flag and the old code path. Once it is deployed, the issue closes with the ring’s record: attempts, CI minutes, credits and grams of CO2e.
Leaves in GitLab
- Cleanup merge request
- Closed issue with the ring record
Guardrails and refusals
When production disagrees with a fix, the ring does not argue. The flag goes off, and the ring either tries again with the new evidence or hands the ticket to a person, with the reason written on the issue. Those rings sit in the ledger next to the ones that worked.
Fences around the agents
-
Their notes stay internal
The three agents are GitLab Duo flows that can only write internal notes. Every public word on a ring issue comes from the conductor.
Check:
.gitlab/duo/flows/*.yml -
No production credentials
The agents read the issue and write code or drafts. Reading traces, switching flags, merging, replying and closing are done by the conductor, which is plain deterministic code.
Check:
ring/lib/tick.ts -
Charter check
An agent’s change may touch only
server/andtest/ring/and add only its own flag. Anything else, the charter included, fails the pipeline.Check:
charter:check,charter.yml -
Negative control
The regression test must fail on the merge base, pass with the flag on, and fail with the flag off. A test that proves nothing does not merge.
Check:
ring:negative-control -
Reply gate
The reply is checked before it is sent. A refused draft never reaches the customer.
Check:
ring/lib/reply.ts -
Signed spans
Verification only counts spans that carry a signature over the fields it reads. The observability ingest is not authenticated, so unsigned spans are ignored.
Check:
server/telemetry.js,ring/lib/signing.ts
When production disagrees
-
If production shows no failing request for the customer
then the ring asks them one question and writes no code.
ring::needs-info -
If switching the flag off does not bring back the old behaviour
then the stop drill fails and a person takes the ticket. A fix that cannot be undone does not stay on.
ring::human -
If the reporter’s requests still fail with the fix on
then the flag goes off at once, with no build and no deploy, an incident opens, and the fix agent tries again with the new evidence.
rollback, incident
-
If the second attempt fails too, or the ring spends more credits than its budget
then a person takes the ticket, with the reason on the issue.
ring::human -
If the fleet’s error rate passes 1% during the ramp
then the flag goes back off and the ring tries again.
rollback
-
If the reporter sends no requests on the fixed path for an hour
then the fix cannot be verified for them, so a person takes over.
ring::human
Numbers from the ledger
Read from ledger.json, which the pipeline rebuilds from the GitLab issues every hour and on every push to main.
Credits and grams of CO2e are modeled, not measured. What is counted and what is estimated is in CLAIMS.md.
Open the ring ledger- Rings run
- …
- Time to fixed for the reporter
- …
- Time to everyone
- …
- Fix attempts and rollbacks
- …
- Handed to a person
- …
- Credits per finished ring
- …
- CO2e per resolved report
- …
Check it yourself
Nothing here needs taking on trust. Each claim points at a GitLab object, a test or a file.
- Review it in five minutes Where to look, in order: a finished ring, its merge request, the refusal, the pipelines, the app. JUDGES.md
- What is real and what is not Every claim with its tier: verified live, reproducible, modeled, or not claimed. CLAIMS.md
- Repository The conductor, the agents’ flows, the charter, the pipeline and the app. gitlab.com/ring-spike/fixed-for-you
- Pipelines Merge requests from the ring, the main pipelines that ship them, and the hourly ring tick. gitlab.com/ring-spike/fixed-for-you/-/pipelines
- The live app It is Kutt. The customers using it are synthetic and come by every five minutes. kutt-production-iao4gvr3pa-od.a.run.app
- The ring ledger Every ring, newest first, with its steps, attempts, flag history and cost. rings