AI CodingAI Agent

An Alarm Clock and an Acceptance Check Can Maintain a Codebase

Boris Cherny recently ran an experiment. His team set up a dedicated Slack channel where Claude runs daily routines to handle mechanical maintenance across iOS, Android, desktop, Web, CLI, and the Agent SDK. Over several weeks, these routines submitted a total of 388 PRs. As of his post, 180 of them had passed Claude Code Review along with human review and were merged into main.

A clock, a checklist, and a pending review card on a light desk

Many people intuitively treat these numbers as simple model hype, thinking Claude can already maintain software on behalf of Anthropic. Others dismiss it as nothing more than attaching Claude to a scheduled job. Both views miss the point. The most notable aspect of those 388 PRs cannot be credited to how smart any single conversation was. A maintenance mechanism that launches automatically every day is steadily feeding changes into the main branch. What practitioners should really examine is the infrastructure supporting this mechanism.

This aligns directly with the observations we discussed in Harness Engineering. When OpenAI used Codex to build internal products, the model readily mimicked degraded coding patterns already present in the repository. When Cursor modified the same codebase in parallel, bottlenecks emerged in coordination and merging rather than in generating individual code snippets. Lessons from both sides point to the exact same conclusion: once routine labor is handed over to agents, what truly determines success or failure is the environment, the constraints, and the acceptance criteria. OpenAI initially dedicated 20% of engineering time every Friday to manually clean up slop, but quickly found it unsustainable. They subsequently switched to having Codex run in the background to periodically scan for drift, score issues, and submit fix PRs. Cursor delegated the implementation layer to workers. Cherny took it one step further by detaching the trigger from individual chat sessions and handing it over to a routine that rings on schedule every day.

388 PRs Look Like Model News, but Are Actually Infra News

The setup shown in the original post is actually quite straightforward. In a channel named proj-claude-maintains-apps, Claude runs routines every day, producing GitHub PRs. Before merging into main, all 180 changes went through automated and human reviews. If a run produced unsatisfactory results, the team did not just patch that single PR; they also instructed Claude to adjust the routine definition directly so that the next day’s run would follow updated rules.

In the YC interview, Cherny described local loops as essentially scheduled tasks, and routines as that same logic moved to the cloud so they keep running even when a laptop is closed. This matches the core point from our discussion in Loop Engineering: loops exist everywhere, but what truly matters is how they are verified, observed, and adjusted for the next run. He also noted that recurring tasks do not need to share a complete conversation context, but they can share memory. These two insights anchor the problem in engineering reality. As long as yesterday’s traces are captured in the repository, execution logs, PRs, and routine configurations, running a fresh context from scratch every day works seamlessly even after closing every chat window.

The numbers 388 and 180 show that this pipeline continuously produced candidate PRs over recent weeks. Among submitted PRs, approximately 46.4% were merged into main. This figure does not represent model accuracy or first-pass success rate. Its denominator is the count of submitted PRs, excluding the total number of identified issues or total agent execution rounds. As for the remaining 208 unmerged PRs, public disclosures do not specify whether they were rejected, duplicate, stale, or queued. This highlights a concrete reality: candidate submissions must naturally exceed actual merges. The review funnel is an intrinsic part of the mechanism rather than an afterthought.

Two Old Paths: Hardcoded Programs or One-Off Chats

In the past, automated maintenance essentially followed two paths: hardcoding the logic into programs, or having a person open an ad-hoc chat session. Taking the first path meant turning maintenance into hardcoded scripts and rules. You relied on static analysis to guess whether code was called, ran a linter to check for duplicate logic and naming conventions, and tightly coupled chunking, retries, and stitching in the workflow. We fell into this trap when working on Chinese-to-English translation pipelines. When input text grew long, models began missing context: terms translated properly earlier would shift in later paragraphs, Chinese characters would occasionally slip into outputs, and API timeouts occurred frequently. To guard against failures, we had to segment text chunk by chunk, inject glossaries, write regex patterns to catch leftover Chinese characters, and log failure checkpoints. While output success rates improved, immense effort was drained by maintaining that brittle, hardcoded pipeline. A program can never handle unexpected cases beyond the handful of rules written in advance.

Dead code elimination is even harder to constrain with hard rules than translation. Where a compiler can verify static unreachability, removal is naturally safe. However, when encountering code that appears untouched but cannot be definitively proven dead by the compiler, even the most elaborate detector will miss edge cases or flag false positives. As rules pile up, maintaining the detector itself becomes a persistent burden on the team.

The second path involves a developer opening a chat window manually, feeding code to the model, and asking it to submit a PR. Today’s models handle such one-off tasks with ease. The problem is that once the session closes, maintenance stops. Even if your prompt asks it to continue tomorrow, it will not run on its own. When the terminal process exits, last night’s logs sit idle on disk, with no mechanism to feed them back into the model’s context.

Both traditional approaches share the same underlying premise: either hardcode all decision logic into programs in advance, or keep a human tethered to the screen. Result certainty introduces a different paradigm, sidestepping this longstanding convention entirely.

Result Certainty Makes cron and webhook Far More Valuable

Adopting result certainty fundamentally shifts the approach. Instead of rigidly prescribing every single step, we only need to define what the destination looks like and how to verify it once reached. How the agent navigates the intermediate steps is up to the agent: it can inspect before modifying, or test and tweak concurrently. The agent can read files left behind by previous runs, execute verification scripts, and fix issues as errors arise. Engineers save their energy to focus on final acceptance verification rather than attempting to precompile every plausible branch into code.

Cherny’s routine for dead code elimination follows this exact pattern. Where code is statically unreachable, it is removed directly. For uncertain, suspected dead code, logging instrumentation is inserted on day one; on day two, the routine inspects the logs to confirm whether the code was truly unused before opening a PR proposing its deletion. Engineers do not need to build complex programs proving that a piece of code will never be invoked. They only need to define a two-day expected outcome: instrument and observe on the first day, then act on the data on the second day. The agent navigates the exploration in between, as long as the acceptance criteria remain crystal clear.

A two-beat diagram illustrating initial observation followed by a keep-or-remove decision

In this setup, triggers only need to perform pure wake-up duty: ringing at scheduled intervals or firing immediately upon release events, failing CI builds, or newly submitted PRs. A scheduled job remains a scheduled job, and a webhook remains a webhook. What truly gains exponential value is the execution environment attached behind the trigger. Moving beyond the old model of running static scripts step by step, it transforms into an intelligent environment capable of reviewing last night’s logs, writing scripts to run verification, and autonomously determining the next step.

On the surface, a scheduled task is still just a scheduled task, but the architecture behind the trigger no longer requires complex flowcharts handling every edge case. While this pattern works for one-off tasks as detailed in From Process Certainty to Result Certainty, Cherny’s insight extends the same logic across days of continuous operation. If a feedback loop requires constant human supervision to function, it remains merely an assistant tool rather than genuine maintenance infrastructure.

This Infra Layer Should Still Be Very Thin

Since intricate logic is delegated to agents, there is no need to bloat the infrastructure layer into a massive workflow engine. Looking across current publicly shared practices, there are only four lightweight building blocks that teams can immediately put to use.

A clock, logs, a stamp, and a folder placed side by side on a desk

The first component is the wake-up mechanism. Cherny chose a daily scheduled run, and product documentation also notes that routines support triggers via API or GitHub events. Whether those 388 PRs involved a hybrid of multiple trigger types is not detailed in public sources. In production, choosing one convenient trigger is sufficient, such as a daily scheduled scan or a post-release check, without overengineering a complex trigger topology prematurely.

The second component is offloading the previous run’s context outside the model. Newly added log instrumentation, commit histories, submitted PRs, and routine definitions themselves are far more useful than chat logs. Recurring tasks do not need to carry the entire conversation history; each subsequent run can start fresh from a clean state. The model should read objective artifacts stored in the repository, since chat histories are ephemeral. Offloading context does not mean discarding it. When the next day’s session wakes up, it first needs to know where the previous run left off and why it stopped. We automatically export daily sessions from various CLIs into unified Markdown archives, paired with a two-stage retrieval mechanism (keyword search followed by semantic search), allowing a new agent run to search the archives whenever context is missing (exported using ai_session_export, with retrieval skills in context-infrastructure). Once sessions are exportable and searchable, cross-day shared memory becomes something the next run can actually read, mirroring how the dead-code routine consults yesterday’s logs. Materializing context as files also yields unexpected benefits. In OpenAI’s evaluation environment, several agents autonomously transformed a package proxy service into a shared message board across execution cycles without human instruction, giving rise to cluster-level coordination through shared files (case retrospective). As long as shared storage satisfies basic prerequisites, subsequent intelligent runs can build on files left by prior ones.

The third component is clearly defining the boundaries of completion. For dead code cleanup, completion criteria can be made concrete: statically unreachable code is completely removed, uncertain areas are instrumented with logging, and PRs proposing removal are created only after logs confirm zero usage. The same applies to translation tasks, where definition of done means no leftover Chinese text, clean formatting, and consistent terminology throughout. If what constitutes completion cannot be clearly specified, running scheduled tasks will only churn out an endless stream of low-quality submissions. As we discussed in HANDBOOK.md experiment, result certainty can also fail; post-mortems identified vulnerabilities in runtime feedback, tiered state, and submission gating.

The fourth component is strictly guarding the gate to main. Among submitted PRs, all 180 merged by the time of the post underwent both automated and human reviews. Writing code and merging code are fundamentally separate concerns; the 46.4% merge rate underscores the presence of this review funnel. If candidate submissions surge, human reviewers can easily fall into rubber-stamping changes based on green CI checks and concise summaries. Once a team’s review bandwidth is exhausted, the entire pipeline gets bottlenecked at review rather than at the model’s ability to produce code.

For low-frequency, single-routine executions, heavy machinery like message queues, distributed leases, and exactly-once processing is unnecessary. Those mechanisms become relevant only when wake-up frequency scales significantly and concurrent submissions begin colliding. For teams adopting this pattern today, starting lightweight is the most pragmatic approach.

What You Can Copy Is the Mounting Pattern, Not the Internal Architecture

OpenAI’s background cleanup, Codex’s scheduled jobs, and the automation capabilities in Cursor and Devin all aim to productize the process of waking up agents. Today, daily coding harnesses across different vendors share strikingly similar features. As we outlined in our side-by-side comparison, delayed triggers and cron schedules are standard offerings. Public API documentation confirms they support scheduled launches, but does not guarantee equivalent merge outcomes, nor does it establish standard solutions for false negatives, deduplication, and automated retries. Similarly, Anthropic has not made its internal implementation public, and blindly speculating about internal architectures is rarely productive.

What can genuinely be adopted is the mounting pattern of this mechanism. Select a routine task that was previously difficult to hardcode into scripts yet simple and unambiguous to verify, attach a clock or event trigger to it, and express acceptance criteria in a format legible to the next agent run. In terms of permissions, grant it only suggestion rights: never provide direct merge privileges, and never expose production credentials. In the Clinejection incident, untrusted issue titles were injected into a pipeline with shell access, leading directly to token exfiltration. In the case of PocketOS, an agent unable to find credentials in a test environment retrieved high-privilege tokens from unrelated files and deleted production volumes along with same-domain backups in seconds. These failures stem entirely from excessive permission exposure and have nothing to do with prompt engineering quality.

If run results fall short of expectations, refine the routine that will execute tomorrow rather than inserting ad-hoc conditionals into code. Cherny emphasized this approach in his public talk. A PR that seemingly passes cleanly on the first try may well rely on prior iterations to the routine definition. Apparent first-pass success often reflects an underlying pipeline that has already been extensively refined.

Accustomed to process certainty in the past, developers routinely invested effort into building exhaustive, intricate programs. Shifting to result certainty naturally redirects focus toward triggers and acceptance contracts. Those seemingly mundane scheduled jobs quietly turn into high-leverage infrastructure.