The question is not whether an LLM can write code for your project. It already can. The question is whether a project can continue to evolve, fix its own bugs, add its own features, and improve its own quality without you ever opening a terminal, writing a prompt, or reviewing a pull request.
This is the self-evolving repository: a GitHub project where every function of the maintainer has been replaced by an automated loop driven by LLMs. No steering. No human-in-the-loop. The maintainer sets it up once, walks away, and the project keeps moving.
I want to be precise about what this means, what it requires, and where it breaks.
What Full Automation Means #
Most LLM-assisted development today is interactive. A developer describes a task, the LLM writes code, the developer reviews, requests changes, and merges. The developer is the steering wheel. The LLM is the engine.
Full automation removes the steering wheel. The project must decide for itself what to work on, implement the work, verify it, and ship it. The maintainer who set it up does not intervene in the loop.
This is a fundamentally different problem from “use an LLM to write faster code.” It is the problem of encoding every judgment a maintainer makes into a system that can execute that judgment autonomously, reliably, and indefinitely.
A maintainer of an active project does many things. They triage bug reports. They decide which feature requests align with the project’s direction. They prioritize competing work. They review contributions. They fix CI when it breaks. They update dependencies. They write documentation. They make architectural decisions. They decline changes that would make the codebase worse.
Each of these is a decision that currently requires human judgment. Full automation means building a system that makes each of these decisions without the human.
The Autonomous Loop #
A self-evolving repository runs a continuous loop.
Observe → Decide → Implement → Verify → Ship → LearnEach stage must be fully automated.
1. Observe #
The system continuously monitors signals about the project’s state. Open issues and their content. Pull requests from external contributors. CI failures and test results. Dependency vulnerability alerts. User feedback in discussions. Stack Overflow questions mentioning the project. Download and usage statistics. Error reports from production telemetry if the project is a library or service.
These signals are the system’s eyes. Without them, the project is blind to what needs attention. The richer the signal sources, the better the system can prioritize.
A project that only monitors its own issue tracker is operating with tunnel vision. A project that also monitors community discussions, ecosystem health, and downstream breakage has a much fuller picture of where to invest effort.
2. Decide #
This is the hardest stage, and I will return to it.
Given the observed signals, the system must decide what to work on next. This is not just “pick the highest priority issue.” It is a sequence of judgments: which problems are worth solving, which are urgent, which can wait, which should be declined, which require architectural changes versus incremental fixes.
The decision stage encodes the maintainer’s judgment about what matters. If this encoding is poor, the project will be busy but not productive, shipping changes that do not move the project in a meaningful direction.
3. Implement #
The system decomposes the chosen work into tasks and generates code. This is the part that LLMs are already good at. Given a clear specification and sufficient context about the codebase, current models can produce working implementations for most routine tasks.
The implementation stage benefits from the same patterns that work in interactive LLM development: competitive generation (multiple attempts, best one selected), iterative refinement (generate, evaluate, regenerate), and specification-driven development (the spec is authored before the code).
The difference is that in the autonomous loop, the specification is also generated by the system, not by a human.
4. Verify #
Before any change ships, it must pass automated verification. This is the quality gate that replaces human code review.
The verification pipeline should include: the existing test suite, static analysis and linting, security scanning, type checking, and scenario-based validation where an LLM evaluates whether the implementation satisfies the specification.
As I argued in Rethinking Code Review in the Age of LLMs, human code review of LLM-generated code is the lowest-value activity in the pipeline. Automated verification is not just faster, it is more consistent and more reliable for the kinds of checks that matter at this stage.
The critical requirement is that verification criteria are defined before implementation, not after. If the system writes tests to match what it already implemented, the tests prove nothing. The specification and its acceptance criteria must exist first.
5. Ship #
Verified changes are merged and released. This stage is mostly mechanical: merge the pull request, run the release pipeline, publish the package, update the changelog.
The one non-obvious requirement is a rollback mechanism. If a shipped change introduces a regression that the verification pipeline missed, the system needs to detect the regression in production telemetry and automatically revert. Without this, errors compound.
6. Learn #
The system records what worked and what did not. Every failed implementation, every reverted change, every missed bug is an input to future decisions.
This learning takes several forms. Failed prompts and their corrections become few-shot examples for future implementations. Bugs that escaped verification become new test cases. Decisions that led to regressions update the prioritization model. Architectural patterns that caused repeated problems become constraints the system avoids.
Over time, the system accumulates institutional knowledge the way a human maintainer does, but in a form that is explicit, versioned, and transferable.
The Direction Problem #
The hardest problem in a self-evolving repository is not implementation. It is not verification. It is not even CI automation.
It is direction.
When a human maintainer decides what to work on, they are applying judgment that is difficult to articulate. They know the project’s trajectory, the community’s needs, the competitive landscape, and the technical debt that is becoming critical. They have taste. They have a vision for what the project should become.
Encoding this judgment into an autonomous system is the real challenge.
The roadmap as a steering mechanism #
The maintainer’s initial setup must include a machine-readable roadmap. Not a vague vision statement, but a structured document that defines: the project’s purpose and non-goals, the target user and their needs, the quality bar for changes, the architectural principles that must be respected, and the current priorities ranked by importance.
This document is the project’s constitution. Every autonomous decision is evaluated against it. When the system decides what to work on, it checks the decision against the roadmap. When the system reviews a contribution, it checks whether the contribution moves the project toward a roadmap goal.
The roadmap does not need to be exhaustive. It needs to be sufficient to distinguish work that matters from work that does not. This is a lower bar than most people assume. Most of a maintainer’s triage decisions are not subtle architectural judgments. They are straightforward: this bug affects users, fix it; this feature request is out of scope, decline it; this dependency has a security vulnerability, update it.
Direction from external signals #
The roadmap provides static direction. External signals provide dynamic direction.
If the system observes that a particular error message is appearing frequently in community discussions, that is a signal to improve the error message or fix the underlying issue. If the system observes that a downstream project broke after a recent release, that is a signal to fix the breaking change. If the system observes that a dependency released a major version, that is a signal to evaluate the migration.
These signals allow the project to evolve in response to its environment without a human pointing the way. The system reacts to what is actually happening rather than to what someone predicted would happen.
The drift problem #
Signal-driven direction carries a fundamental tension. A self-evolving repository that only reacts to external signals will optimize for whatever those signals measure. If the signals are bug reports, the system will become excellent at fixing bugs and terrible at anything else. If the signals are feature requests, the system will accumulate features and lose coherence.
This is Goodhart’s law applied to software maintenance: when a measure becomes the target of an autonomous system, it ceases to be a good measure.
The roadmap exists to counteract this drift. It is the fixed point that keeps the project aligned with its original purpose even as the system optimizes for observable signals. But the roadmap itself can become stale. A project’s context changes over time. User needs shift. The ecosystem evolves. A roadmap written in January may be wrong by July.
A fully autonomous system needs a mechanism for updating its own roadmap. This is where the direction problem becomes genuinely difficult. Updating the roadmap means making a judgment about what the project should become, and that judgment requires understanding the project’s users, ecosystem, and competitive position at a level that current LLMs can approximate but not fully replicate.
The pragmatic solution is not to solve this perfectly but to bound it. Let the system make small roadmap adjustments based on observed signals, but require large directional changes to go through a human review. This keeps the system autonomous for 95% of decisions while preserving human oversight for the 5% that determine the project’s long-term trajectory.
Quality Without a Human #
The quality question is the one most people get stuck on. “How do you trust code that no human reviewed?”
The answer is the same one I gave in The Future of Code Review: you do not trust the code, you trust the verification system.
A self-evolving repository needs a verification pipeline that is more rigorous than what most human-maintained projects have today. Not because the code is worse, but because there is no human backstop.
The pipeline should have multiple independent layers, each catching different classes of problems.
Unit and integration tests catch functional regressions. These should be comprehensive and fast. The system should be able to run the full suite in minutes, not hours.
Property-based testing catches edge cases that example-based tests miss. For pure functions and data transformations, property tests can generate thousands of inputs automatically, surfacing bugs that a human would never think to test.
Static analysis catches type errors, security vulnerabilities, and common anti-patterns.
Tools like Semgrep,
CodeQL, and language-specific analyzers should run on every change.
Mutation testing verifies that the test suite is actually meaningful.
If you can mutate the code and the tests still pass, the tests are not testing what you think they are.
This is especially important when the tests themselves are LLM-generated.
Scenario-based validation uses an LLM to evaluate whether the implementation satisfies its specification. This is the layer that catches semantic problems that automated tests miss: the code works, but it solves the wrong problem.
Adversarial verification has a separate agent actively try to break the implementation. This agent writes tests designed to fail, probes edge cases, and attempts to find inputs that produce incorrect behavior. It is the automated equivalent of a hostile code reviewer.
The key insight is that each layer should be independent. If the same LLM that wrote the code also wrote the tests and also ran the review, the correlated failure rate is high. The system will make the same mistake in implementation, tests, and review because they all share the same blind spots.
Diversity of verification methods reduces correlated failures. Static analysis does not share blind spots with property testing. Mutation testing does not share blind spots with scenario validation. The layers are strongest when they are structurally different, not just different invocations of the same model.
What Can Go Wrong #
A self-evolving repository is a complex autonomous system. Complex autonomous systems have failure modes that are hard to predict.
Silent quality decay #
Silent quality decay is the hardest failure mode to notice. The system ships changes that pass all verification layers but gradually degrade the codebase’s quality. Each individual change is defensible. The cumulative effect is a codebase that is harder to maintain, slower to evolve, and full of subtle interactions that no one understands.
This happens when the verification pipeline measures immediate quality (does this change pass tests?) but not systemic quality (does this change make the codebase healthier?). Metrics like cyclomatic complexity, coupling, and test coverage can help, but they are proxies, not ground truth.
The complexity spiral #
Without a human saying “this is too complex, simplify it,” the system may accumulate complexity over time. Each new feature adds code. Each bug fix adds special cases. Each dependency update adds compatibility layers. The codebase grows without bound because nothing in the autonomous loop says “stop adding, start removing.”
A self-evolving repository needs an explicit simplification loop. The system should periodically identify the most complex parts of the codebase and attempt to simplify them, even if no bug is forcing the change. This is technical debt reduction as an automated process.
Specification drift #
When the system writes its own specifications, the specifications can drift from what users actually need. The system optimizes for specifications it can satisfy, not specifications that matter. Over time, the project accumulates well-implemented features that nobody uses.
This is the autonomous version of the problem I described in The Shifting Bottleneck: when implementation becomes free, deciding what to implement becomes the hard part. In a self-evolving repository, the decision problem is fully automated, which means the drift can go unnoticed for longer.
Cascading failures #
A single bad change that passes verification can break downstream functionality in ways that the verification pipeline does not catch. The system then generates fixes for the symptoms rather than reverting the cause. Each fix introduces new changes, each of which can introduce new problems. The system enters a fix loop, shipping increasingly desperate patches that make the situation worse.
The defense against this is blast radius limitation. Changes should be small, merged incrementally, and monitored for downstream impact. The system should have a threshold: if more than N changes in a row require fixes, stop and flag for human attention rather than continuing to patch.
Cost runaway #
Every iteration of the autonomous loop costs money: API calls for generation, verification, and decision-making. A system that is stuck in a fix loop, or that is attempting overly ambitious changes, can burn through significant compute before anyone notices.
The system needs explicit budgets. A maximum number of iterations per change. A maximum cost per change. A maximum number of changes per day. When a budget is exceeded, the system pauses and logs the situation rather than continuing to spend.
What the Maintainer Does Once #
The maintainer’s role in a self-evolving repository is concentrated entirely in the setup phase. Everything that happens after setup is automated.
The setup has five components.
The roadmap. A structured document defining the project’s purpose, non-goals, priorities, quality standards, and architectural principles. This is the single most important artifact. It determines whether the autonomous system makes good decisions or busy decisions.
The verification pipeline. The combination of test suites, static analysis, property tests, mutation tests, scenario validation, and adversarial verification that gates every change. This pipeline must be in place and passing before the autonomous loop starts. If the verification pipeline is weak, the autonomous system will ship low-quality code.
The decision policy. The rules that govern how the system prioritizes work. What signals does it monitor? How does it rank competing tasks? When does it work on bugs versus features versus technical debt versus documentation? This policy encodes the maintainer’s judgment about how to allocate attention.
The guardrails. Budget limits, blast radius constraints, escalation triggers, and rollback mechanisms. These are the safety systems that prevent the autonomous loop from causing damage when something goes wrong.
The learning infrastructure. The mechanisms by which the system records outcomes and feeds them back into future decisions. This includes the few-shot example library, the bug-to-test pipeline, and the decision evaluation framework.
Once these five components are in place, the autonomous loop can run. The maintainer’s ongoing involvement is limited to reviewing escalation reports, the small percentage of decisions that the system flags as requiring human judgment.
When This Makes Sense #
Not every project should be a self-evolving repository.
This approach makes sense for projects with: clear specifications and measurable quality criteria, active user bases generating feedback signals, maintenance-heavy codebases where most work is bug fixes and incremental improvements, and well-established architectures where most decisions are routine.
It makes less sense for projects that are: in early exploration where direction changes frequently, in domains where correctness is safety-critical, in codebases with poor test coverage or unclear specifications, or where the competitive advantage is design taste that is hard to encode.
The threshold question is simple: can you write down the rules a competent maintainer would follow, well enough that following them mechanically produces good outcomes? If yes, the system can work. If no, the system will be autonomous but not effective.
The Deeper Question #
A self-evolving repository raises a question that I explored in Scaling the LLM Agent Company: when the system is its prompts, its pipelines, and its proprietary context, what is the project?
The project is no longer its code. The code is a byproduct of the system that generates it. The project is the roadmap, the verification pipeline, the decision policy, the guardrails, and the accumulated learning data. These are the artifacts that determine what the project becomes.
This reframes what it means to maintain a project. The maintainer’s most important work is not writing code, reviewing pull requests, or fixing bugs. It is designing the system that does all of those things autonomously. The maintainer becomes an architect of processes rather than an executor of tasks.
The project that outlives this setup is the one where the autonomous system makes decisions the maintainer would have made, ships quality the maintainer would have approved, and evolves in a direction the maintainer would have chosen.
The question is whether you can encode your judgment well enough to make yourself unnecessary.
If you can, the project evolves without you. If you cannot, no amount of automation will compensate for the missing taste.
See also #
- Scaling the LLM Agent Company - how agent companies invert traditional scaling constraints
- The Shifting Bottleneck - how AI moves bottlenecks up the decision chain
- The Future of Code Review - the Software Factory paradigm and autonomous verification
- Rethinking Code Review in the Age of LLMs - why human review of LLM code is low-leverage
- Software Engineering Teams in the Age of AI - what processes to keep and what to eliminate
- The Importance of Context When Interacting with LLMs - context engineering as the determinant of output quality