# Building with mini, Part 4/9: The main loop — next plan do done

> Source: <https://dev.to/stkremen/building-with-mini-part-4-the-main-loop-next-plan-do-done-344a>
> Published: 2026-07-01 11:00:00+00:00

pycalc has a vision (Part 2) and a backlog (Part 3) — and still not a single line of Python. Today we fix that. Four commands form the heart of mini: **propose, break down, build, close**. One turn of the loop = one phase = one commit.

`next`

— propose

```
mini next
```

`next`

is the entry point of the loop, and the only step that begins with a question: do you have your own idea, or do you leave it to the agent? I left it to the agent — and it's worth showing what it did with last episode's backlog:

The backlog has two items so far ([1]

`**`

and`%`

, [2] reading from stdin), but both are explicitly out of scope for this version (non-goals), so neither fits the first phase.

This is exactly the interplay that `project.md`

and `todo.md`

exist for: the backlog offered itself, the non-goals stopped it. Instead, three candidates came up — tokenizer with positions, a CLI skeleton, a walking skeleton — each with its trade-off:

I propose candidate 1: Tokenizer with positions.Why not the walking skeleton: it sounds tempting, but for a project this small the rewriting overhead outweighs the benefit — the pipeline has only three pieces, and in three phases it will be end-to-end anyway. The trade-off of candidate 1: until there's a CLI, you can't poke at anything by hand; verification is purely through tests.

After approval the agent saves the phase itself, via `mini next --apply --title … --goal …`

. State is never changed by the model's hand:

```
Phases:
  [proposed] > 1. Tokenizer with positions

  Next: mini plan (break it down) or mini do (run directly)
```

`plan`

— break down

```
mini plan
```

`plan`

breaks the phase into steps — a short title plus a one-sentence detail (that pairing is deliberate: only the titles go into later steps' prompts, the detail is fetched when needed). For the tokenizer it produced five steps, from the `Token`

NamedTuple through the number scanner into `Decimal`

to the unittest table. And here too a decision surfaced that would otherwise only emerge in the code:

`.5`

and`2.`

are deliberately rejected (simplest rule with exact error positions; trade-off:`.5`

is valid in many calculators — say so if you want it supported and I'll adjust step 3).

Approved, saved (`mini plan --apply`

reads the steps from stdin):

```
[planned]  > 1. Tokenizer with positions
  Steps:
    [todo]     Token type and CalcError in pycalc.py
    [todo]     tokenize() loop: operators, parens, whitespace
    [todo]     Number scanning into Decimal
    [todo]     Invalid character raises CalcError with position
    [todo]     unittest case table in test_pycalc.py
```

`do`

— build

```
mini do
```

Only now does code get written. The session gets the phase, the steps and a reference to the project — not the whole conversation history. The agent ticks steps off as it goes (`mini do --apply --step-done "<title>"`

), so `mini status`

shows live progress, and at the end it writes a **run report** to `.mini/run/phase-001.md`

: the verdict, the step statuses, and notes beyond the plan. Those notes are the most valuable thing in the report:

- I deliberately rejected
`str.isdigit()`

— it accepts Unicode digits like`٣`

, which`Decimal()`

would happily parse too. A helper restricts numbers to ASCII 0-9; there's a test that`1+٣`

raises an error at position 2.- I verified the "no input ever produces an unhandled exception" claim with a fuzz over 20,000 strings — only
`CalcError`

was ever raised.- One of my own test expectations was off by one (
`10.25+0.75`

positions); the tokenizer was correct, the test data was fixed.

All five steps done, 27 test cases green. And note what *didn't* happen: no REPL, no `sin`

, no colors. The non-goals hold.

`done`

— close
`done`

is the loop's human gate — the one place mini insists on a person. State, incidentally, now reminds you itself that there's something to close:

```
[doing]    > 1. Tokenizer with positions
            ⚠ stuck: phase "doing", but it has no open steps — close it via mini done
mini done
```

The agent summarizes the phase from the run report, proposes an entry for `CHANGELOG.md`

, and asks the one thing that matters: **does it work for you?** Verification is my job, not its:

```
python3 -m unittest -v
...
Ran 3 tests in 0.001s
OK
```

After confirmation it writes the CHANGELOG (Keep a Changelog format, Unreleased section) and calls `mini done --apply`

. That does three things at once: moves the state, writes the **phase memory** to `.mini/memory/phase-001.md`

(goal, steps, run report — what the next phase will find useful), and wraps the entire phase's work into a single commit:

```
git log --oneline
a01eb36 Phase 1: Tokenizer with positions
9cf1df1 init: mini project setup
```

The version isn't bumped by default and nothing is pushed — both are opt-in (`--bump patch --push`

), no surprises on the remote.

```
Phases:
  [done]       1. Tokenizer with positions (took 2m 6s)

  Next: mini next (proposes the first phase)
```

Two minutes six seconds from `do`

to commit. And the backlog? Still 2 open items — the loop never touched it, because it never came up.

This is where the whole architecture from Part 0 pays off. Every step of the loop starts from **saved state**, not from a conversation: `plan`

doesn't need to know what was said in `next`

, it reads the phase from `.mini/`

. Between phases `/clear`

is recommended — the context is thrown away, because everything that matters survives in files: state in `state.json`

, experience in the phase memory, history in git and the CHANGELOG. The conversation is disposable; the state is permanent.

A trade-off, to put it fairly on the table: one phase = one commit means a half-done phase isn't in git. If a `do`

session crashes mid-way, the code on disk stays (so do the report and the ticked steps), but the commit doesn't — which is why keeping phases small helps, exactly as `next`

enforces (1-3 days, one verifiable goal).

And about those three human stops (approving the proposal, approving the plan, verifying in `done`

): for one phase a day they're priceless, for five phases in an evening they're a chore. That's precisely why `mini auto`

exists — but more on that in a later episode.

The loop can build. Next we'll look at the two human checkpoints around it — `discuss`

, when a phase needs talking through first, and `verify`

, when "the tests passed" isn't enough and it calls for a human UI/UX review.

*mini is open source: npm install -g mini-orchestrator, then mini install-commands in your project. Source and docs on *
