I still reconcile my credit-card spending manually across several spreadsheets. The calculations and automation I've added help, but it's still painful to do every month.
That's the reason for dot-finance. I want an application that imports transactions, works out how much needs to come from different accounts, and records what's been settled. It will stay offline and I'll still make the transfers myself.
There's another part to the project though. I've used coding agents on plenty of bounded tasks, and full agentic workflows in my job as a software architect. I want to build my own development loop from scratch for personal projects, with dot-finance as a real application to test it against.
That means working out what happens around the coding. An agent needs enough context to pick up an issue in a fresh session, a way to check its work, and a limit on how long it can spend trying to correct a failure. If a run stops halfway through, I need to know where it got to without reconstructing the whole conversation.
Before writing application code, I started by putting those rules into the repository.
Context that survives the conversation
I began with a specification and asked Codex to review it and grill me on anything unclear before planning the work.
I've been using reusable agent skills for this, including ideas from Matt Pocock's skills collection. A skill gives the agent instructions for a particular kind of work, which saves rebuilding the same prompt each time. The local grilling skill asks one question at a time, gives a recommendation, and waits for a decision. I then used to-issues to turn the prototype work into GitHub tickets.
The conversation is useful for reaching decisions, but a later session needs to find the decisions without reading everything that led to them. I've split that context across three files.
-
spec-file.mddescribes what the application must do. -
development-workflow.mddescribes how an issue moves through implementation, validation, review, and integration. -
AGENTS.mdgives an agent the operating rules for the repository.
For example, staying offline is an application constraint. Using synthetic development data is a rule for doing the work. A missing platform check is unfinished validation. All three need to survive the session in which they were discussed, and each belongs somewhere an agent can find it again.
This also gives me something concrete to review when the process needs changing. I can update the relevant rule rather than leave a correction buried in a chat and hope the next run sees it.
One issue at a time
The initial loop is sequential. It selects one ready issue with completed dependencies, works on an isolated branch, runs the required checks, and sends the result through independent review before integration.
The proposed loop at this stage of the project. The workflow is documented; the controller hasn't been built.
Starting with one issue keeps the coordination manageable. There's one branch to inspect and one set of expected outcomes. I can work out whether the basic loop behaves properly before adding concurrent work and the extra problems that brings.
The issue needs to say how I'll know the work is complete. “Add encrypted backup” leaves too much open. Saving synthetic data on one supported platform, restoring it on another, and checking that the expected state survived gives the agent a result to demonstrate.
Opening a pull request doesn't satisfy that requirement. A green build might not satisfy it either, if the required behaviour was never exercised. The issue stays open until the agreed validation and integration are complete.
The evidence also needs to identify the commit it came from. If a review leads to code changes, the affected checks have to run again. A Windows check that passed before those changes can't simply be carried forward because it's on the same branch.
It's a small bookkeeping requirement with a practical consequence. After an interruption, I need to be able to tell which code passed which checks, and which checks are still pending.
Putting a limit on corrections
In my earlier AI field notes, I described using Gemini to help set up an Octopus Deploy instance. I kept feeding errors back into the conversation, and it eventually suggested running Octopus on PostgreSQL. By then I should have stepped back, checked what was missing from the context, and started again from a better position.
I don't want this loop to depend on me noticing that point every time.
For the prototype phase, I've set an initial limit of three correction attempts or 90 minutes of active agent work, whichever comes first. Those numbers are provisional. They give the first runs a stopping point while I find out whether the limits are useful in practice.
When the budget runs out, the controller should return enough information to investigate or continue deliberately. That includes the issue, branch and commit, checks completed, evidence collected, correction count, remaining problem, and next action. Continuing needs an explicit new budget.
An interruption needs the same care. Restarting a run mustn't reset its correction count or turn an unfinished check into a pass. The plan is to keep GitHub as the record of the work, with a local checkpoint holding enough execution state to resume accurately.
The controller also needs to distinguish a code failure from an infrastructure problem. If a hosted runner is unavailable, editing the application won't help. That platform's validation should remain pending, with the blocker recorded. Otherwise the loop could spend its correction budget changing code that hasn't been shown to be wrong.
These are behaviours I need to test in the controller itself. The prototype plan includes a deliberately failing check, an interrupted run, an unavailable runner, and a review rejection. A successful application build wouldn't tell me whether any of those paths work.
Reviewing the tests and the architecture
Independent review needs to look beyond whether the implementation compiles. Code and tests written together can share the same misunderstanding, so the reviewer needs the requirement, the diff, and the validation evidence. Part of that review is deciding whether the tests would catch a meaningful error in the required behaviour.
I've also asked for LikeC4 architecture diagrams alongside the implementation. I've been a long-term fan of the C4 model and the consistency it brings to architectural discussions. This project gives me a chance to try architecture as code while an agent is making the implementation changes.
The proposed rule is to update the LikeC4 model in the same pull request when component responsibilities, dependencies, storage, or significant flows change. If a change has no architectural effect, the pull request can say so.
The build is intended to validate the model and generate the diagrams. That would catch an invalid model, but it wouldn't establish that the diagram accurately describes the C# code. Checking that agreement remains part of review. Otherwise I could end up with a passing build and an increasingly misleading description of the application.
At the end of this setup stage, I had a specification, prototype tickets, and workflow rules. There was no application or controller yet. The first prototype was planned to establish the desktop and LikeC4 build foundation, followed by investigations into encrypted storage, restoration across platforms, and the guided reconciliation flow. Alongside those application checks, the controller still had to demonstrate that it could stop within its budget and resume without losing track of unfinished validation.

Top comments (1)
Separating runner outages from code errors solves the biggest hidden cost in autonomous development loops. When an agent cannot distinguish an unavailable runner from a failing unit test, it treats infrastructure noise as a negative gradient on its own logic. The model starts modifying perfectly valid code to accommodate an environment failure that it has zero leverage to fix.
A deterministic stopping limit of three retries works like an option premium on developer attention. In unconstrained loops, error feedback does not produce convergence toward correct code. Each failed attempt expands the context window with partial explanations and mistaken diagnoses, which degrades model performance on the next turn. After three failures, the probability of self-correction drops sharply while the risk of architectural drift compounds.
Independent review addressing whether the tests share the implementation's flawed assumptions targets the exact point where synthetic pipelines silently break. A generator grading its own work will always produce passing assertions that verify its misunderstanding rather than the specification. Keeping the acceptance criteria pinned to external invariants is what prevents the loop from certifying a bug as a design choice.