In one minute
Lore Week 2: why our checks stopped in seconds, why a correct build can miss a file, and when a bot may merge
39 merged, about 30 minutes from open to merge (median)
Lab, weekly paper. Week of Mon 19 Oct to Sun 25 Oct 2026, Europe/Istanbul. We counted merged pull requests on Sunday 25 Oct at 21:00 Istanbul time, so the last part of Sunday is not in the count.
This week we merged 39 pull requests. A pull request is a proposal to change our code; usually a coding agent opens it for us, and it is checked before it joins the main version. The typical one merged about 30 minutes after it was opened. Most of the work went into a new product we have not announced (25 merges), then AutoReal (6), an internal repository (6) and lorelabs.co (2).
The week also ran out of something we rarely think about: minutes for our automated checks. Of 242 check runs, 21 failed, and 17 of those were not test failures at all. They stopped within 3 to 7 seconds without running a single step, because our account had used its monthly allowance.
We want to teach three ideas the week made clear:
1. A CI minutes budget. What it is, how it is counted, and why a job that does almost nothing can still cost a full minute.
2. Why a deployed bundle can miss a file even when the code is right. A build copies only the files it can see being used. A file loaded another way can be left behind.
3. A low-risk bot merge rule. When a bot may merge a change that another bot wrote, and what keeps that safe.
Method
How we looked at the week
We listed merged pull requests in each of our repositories, read every one, looked at the automated check runs, and compared each product's state file, a short document that says what exists right now, at the start and end of the week. One internal repository has no state file, so its decision records stand in for it. This count includes internal repositories, so it is larger than the Lab build log, which counts product repositories only. Where a figure comes from a pull request's own text and not from our count, we say so. This is one week of a small team, so the numbers show a pattern and prove nothing.
Idea 1
A CI minutes budget
0 to 3 minutes
one job, 2 min 5 s of work
billed 3
ten jobs of 20 s each
billed 10
skipped before it starts
billed 0, reported as Success
GitHub rounds each job up to the whole minute.
What it is. CI, continuous integration, is the set of automated checks that run on every proposed change: they read the code, run tests and build the app. On GitHub these checks run on rented machines, and for private repositories each account gets a monthly allowance of machine minutes. GitHub's billing page lists 2,000 minutes a month on the free plan and 3,000 on the Pro and Team plans. The minutes are charged to the owner of the repository, not to whoever triggered the run.
Why it matters. When the allowance is used and no payment is set up, or a spending budget is reached, GitHub stops starting jobs. The checks do not fail because the code is wrong. They fail because they are refused. A red cross that means "no budget" looks just like one that means "broken code" until you open it.
How it works, in simple words. Think of a taxi with a minimum fare. GitHub's pricing page says it rounds the minutes and partial minutes each job uses up to the nearest whole minute. So a job that starts, prints "nothing to do" and exits after 10 seconds costs one full minute. Ten tiny jobs cost ten minutes, even if together they did less than two minutes of work. A job that is skipped by a condition before it starts uses no machine at all, and GitHub reports it as "Success". The cheapest check is the one that is never started when it has nothing to look at.
What happened to us. On 24 and 25 Oct our account ran out of minutes, and 17 of the week's 21 failed runs ended within 3 to 7 seconds with zero steps. This was the second time in two weeks; the first was on 12 Oct. One of our pull requests named the surprise: jobs that only printed a skip line still billed a whole minute each.
The response came in layers. First, the heavy tests in AutoReal now run only when the files they test change, and the slow rendering tests are split into four parts that run side by side. Its main check run had a median of about 6 minutes and a slowest of 12, and the fastest real run after the change took about 4 minutes (wall clock, not billed minutes). Then we opened changes in most of our repositories with one pattern: skip drafts, filter by path, use one job per check instead of several small ones, and let a newer push cancel an older check on the same pull request. A company rule for CI use is written and waiting for approval. We chose a small plan upgrade plus efficiency over a much bigger plan.
What others say. GitHub's own pages give the rules: per job rounding up to the whole minute, a skipped job reports success, and a concurrency setting can cancel a running job in the same group. Independent writers make the cost point more bluntly: ten jobs of 20 seconds bill 10 minutes for 200 seconds of real work, and run logs show real durations while the bill shows rounded ones.
How we compare. We had built many small jobs, which is the pattern rounding punishes most, and we were reading wall clock times as if they were the bill. They are not. Most of the fix is still waiting to be merged, so we cannot yet say how much it saves over a month.
Idea 2
Why a deployed bundle can miss a file
project folder
import
path built at runtime
bundle
not copied
new check opens this box
What it is. When we deploy a web app, we do not ship our whole project folder. The build tool makes a smaller package, a bundle, with only the files the app needs at runtime. Next.js has a "standalone" mode that copies exactly those files into one folder that the server runs.
Why it matters. The bundle is what users touch. If it misses a file, the app breaks in production even though every line of code is correct and every test on the full project passed. Tests usually run against the whole folder, where the file is still there.
How it works, in simple words. Packing a suitcase from a list works only if the list is complete. Next.js makes its list by reading the code: it looks for imports and file reads and follows them. Its documentation says plainly that it might fail to include required files in some cases, and gives a setting to add files by hand. A file whose path is built while the app runs can be invisible to that reading.
What happened to us. In AutoReal, approving a post stored a failed draft in production. The cause: the bundle our hosting serves had copied a library's main file but left out a small settings file that the library loads by a path it builds at runtime. The error came before a simpler backup method could take over, because the backup only caught a specific kind of error. The fix adds the missing files to the bundle by hand, lets the backup handle this case, and adds an automated check that runs against the served bundle itself. It merged on 24 Oct at 23:22 Istanbul time.
What others say. Next.js documents both the tracing and its limits. Last week we quoted DORA's advice that the package made by the CI build should be the one used downstream. This incident is that advice in practice.
How we compare. Before this fix, our checks built the app but did not test what is served. Now one check does, but only when the files that shape the bundle change, to save minutes. That trade is reasonable, and it means a new runtime file in an unwatched place could slip through again.
Idea 3
A low-risk bot merge rule
- inspector passed this version
- all checks green
- only docs or tooling config
- no deploy, money, secrets or user facing code
- author is not the merger
- merge order followed
else the founder merges
What it is. Merging is the moment a change joins the main version. Until this week only our founder merged. A low-risk merge rule lets a bot merge certain small changes, such as documentation or tooling settings, as long as it is not the bot that wrote them.
Why it matters. Waiting for one person to merge every docs fix slows everything down, and most of those fixes carry no risk to users. But "low risk" has to be a written test, not a feeling, or it grows until it covers things that do matter.
How it works, in simple words. It is the four eyes principle with a checklist. Our rule allows a bot merge only when all six conditions hold:
- An inspection bot passed the exact version being merged.
- Every required check is green.
- The change touches only docs, plans, records or tooling config.
- It involves no deploy and nothing about money, pricing, legal text, sign in, secrets, CI or anything users see.
- The author is not the merger.
- Any merge order the inspector stated is followed.
Product code, design and releases still go through the founder, who can revoke the rule at any time. Where a merge itself triggers a deploy, no bot merges.
What others say. DORA's research, from the 2019 State of DevOps report, finds that change approval works best as peer review during development, supplemented by automation that catches bad changes early, rather than approval by a distant board. GitHub's protected branch settings can require that the latest push be approved by someone other than the person who pushed it, the same idea as our fifth condition.
How we compare. Our rule matches both: review by a party that did not write the change, plus automated checks, with a narrow written scope. One detail slipped. The rule took effect when it merged on 22 Oct, but its record still said "awaiting decision" for two more days. We did not check whether any bot merged under the rule this week.
Lessons
What we learned
A red cross can mean "no budget". 17 of our 21 failed runs never ran a step. Reading the reason before retrying saves time and, here, more minutes.
Count what you pay for, not what you see. Wall clock time and billed minutes differ, because every job rounds up. Fewer, larger jobs and jobs that skip before they start cost less.
Test the box you ship. Our bug lived only in the served bundle. A check on the full project could never see it.
A backup is only as wide as the errors it catches. We had one, and it did not run, because the error was of a kind nobody expected.
Small pull requests merged fast; big ones waited. The median was about 30 minutes and 25 of 39 merged within an hour, but the three slowest were among the largest, the slowest taking 5.4 days.
State files keep growing in characters. One product's state file almost doubled in characters (up 92 percent) with only 12 more lines. Last week we saw the same in AutoReal.
What surprised us. A new product went from an empty repository on 21 Oct to 25 merged pull requests in five days.
Next
What happens next
From our open pull requests, plans and decision records. Anything marked Proposal is ours and is not decided.
- The CI minutes changes and the company rule for CI use wait for approval.
- AutoReal has a follow up for its chat interface open.
- Work continues on the product we have not announced.
- Proposal: report billed minutes, with every job rounded up, next to wall clock times each week.
- Proposal: run the served bundle check on every merge to main, not only when certain files change, and measure what it costs.
- Proposal: when a check fails in under 10 seconds with zero steps, our agents report it as a billing refusal and do not retry.
- Open questions: how many minutes does the new pattern save over a full month? Has any bot merged under the new rule yet, and did each merge meet all six conditions?
Limits
What we could not verify
- Merges between our count at 21:00 and the end of Sunday.
- Billed minutes for the month. We read wall clock run times only.
- How much the CI changes save. Most are not merged yet.
- Our hosting platforms' own deploy logs.
- Whether the post approval fix works for real customers. The fix was not tested against the live app with a signed in account.
- Whether any bot merged under the new rule this week.
- Direct pushes that never became a pull request.
- External claims are as each source states them.
25 Oct 2026
Sources
We opened each link on 25 Oct 2026 and checked that it loads and says what we use it for.
- GitHub Docs, GitHub Actions billing: monthly minutes per plan, minutes charged to the repository owner, usage blocked when the quota is used and no payment method is set.
- GitHub Docs, Actions runner pricing: each job rounded up to the nearest whole minute.
- GitHub Docs, Using conditions to control job execution: a skipped job reports "Success".
- GitHub Docs, Control the concurrency of workflows and jobs: concurrency groups and cancelling a running job.
- Ravoid, Your CI Bill Moved and Nobody Can Explain Why: the per job rounding example.
- Next.js Docs, output: file tracing, standalone mode, and its limits.
- Vercel, @vercel/nft: the file tracing library Next.js uses.
- DORA, Streamlining change approval: peer review plus automation.
- GitHub Docs, About protected branches: approval by someone other than the last pusher.
Everything else is from our own records, taken 25 Oct 2026. Our repositories are private, so we link nothing from them.