# A routine, in three moves

*A reusable format for turning something you do by hand into something that runs without you. Take it, fill it, use it again — once per routine, before any code is written.*

---

## What this is for

**This is for the moment before a procedure becomes a script.** A command-line routine is a written-down request. Before it is a script it is something you did, and before that it is something you would have asked a person to do. This format is where the doing gets recorded, so that the script has something true to be built from.

The alternative it replaces is the ordinary one: you decide to automate a thing, you describe the thing to a coding agent or to yourself, and the description is written from memory. A procedure recalled is a procedure already tidied — the hesitations gone, the order made to look reasoned, the steps you take for no reason at all indistinguishable from the steps that had to happen where they did. The script inherits all of it and none of it is marked.

**What this protects is the difference between the routine and you.** Most of what you do in a procedure is the procedure. Some of it is habit, and habit written into clean code stops being visible as habit — to you first, and then to everybody who reads it afterwards.

🔵 **A claim of mine, and not one of the rules above. Delete this block and the format still works. This is my hypothesis and not an established finding: an automated routine is the fossil of a habit.** What gets automated is not what somebody specified in advance. It is what became tedious. The mechanism I think is at work is that you cannot see which parts of your own procedure are decisions until you have repeated them often enough to be bored by them. **What would show me wrong:** a routine specified correctly before anybody performed it once, which then survives contact with real use unchanged.

---

## The format

```
CONSTRUCT       the routine as the commands you would actually run,
                in order, not as a description of what they do

RECORD          one row per step, filled in while you are working
THREE RUNS      three different days, a fresh sheet each time, the
                previous sheet unread
TRANSLATE       the record handed over, plus the three things no
                record shows

THE DIVERGENCE  where the automated version differs from what you did
```

Three moves, and the order is the content. The fifth line is the output; the first four are how you get one.

### The sheet

```
 #  WHAT I RAN          WHAT I LOOKED AT TO KNOW      D / A / ?   MINS
 1
 2
 3
 4
 5
```

### What each line is asking

**CONSTRUCT.** The commands, as you would type them, in order. *Check whether the log has moved* is not a step; the command that checks it is a step. Where you do not know the command for something, that is the first thing to go and find. **A thing you have done twice is not yet a routine** — there is nothing to record yet, and starting early gets you a sheet full of a procedure still being invented.

**RECORD.** One row per step, four columns. **WHAT I RAN** is the command as typed, not what you meant by it. **WHAT I LOOKED AT TO KNOW** is the signal that told you this step was the next one, and where that signal was — *the light was still on*, *the last line was older than a minute*, *nothing, I always do this one next*. **Nothing is a real answer and a common one**, and it is the most useful thing on the sheet, because a step whose input cannot be named is a step nothing can automate. **MINS** is roughly how long, and it is here because tedium is what tells you a thing is ready to be automated, and tedium is a number.

**D / A / ?** — **D** if the step is a decision: it had to happen here, in this order, for a reason you can say out loud. **A** if it is an accident: this is how you happen to do it and another order would work as well. **?** if you do not know. **The question mark is the most useful mark on the sheet and it costs nothing.** A sheet with no question marks on the first run is a sheet that was filled in afterwards.

**THREE RUNS.** Three times, on three different days, on a fresh sheet each time, **without reading the previous sheet first**. Then put the three side by side. The steps that appear in all three in the same order are the routine. Everything else is you. Where run one says **D** and run three says **A** about the same step, trust run three: a step you defended the first time and shrugged at by the third was a habit wearing a reason.

**TRANSLATE.** Hand over the rows, not a description of them. Then say the three things no sheet can show and no agent can work out: which rows are **D** and which are **A**, because it will preserve your order either way and it will not hesitate; what the routine does when the input is missing or wrong, which you have met by hand and it has not; and where the routine stops and a person starts. Then read what comes back and annotate it, one comment per step, decision or accident. **Generated code is fluent and reads as though it knows why the order is that order.** Once your accident is written in clean code you will stop being able to see it as an accident, and so will everybody else.

**THE DIVERGENCE.** Run the automated version against a task you have already done by hand, and find where the two differ. Write down what differed and why. **That is the output of the whole format** — not the sheet, and not the script. Anybody can produce a log. Nobody predicts their own divergence in advance.

---

## A worked one

```
CONSTRUCT       Six commands: check the feed is live, find files newer
                than the last run, convert them, move them, write the
                stamp, tail the log.

RECORD          Run 1, Tuesday, filled in at the desk while doing it.

 #  WHAT I RAN                   WHAT I LOOKED AT TO KNOW     D/A/?  MINS
 1  systemctl is-active feed     Nothing. I always start here.   A     1
 2  find in/ -mmin -60           Step 1 said active               D     1
 3  ./convert.sh in/*.raw        The find printed something       D     9
 4  mv out/* archive/            Nothing — habit                  ?     1
 5  date > .laststamp            Nothing — habit                  ?     1
 6  journalctl -fu feed          I do not trust step 3            A     4

THREE RUNS      Runs 2 and 3 on Thursday and the following Monday.
                Step 4 was A both times. Step 5 was D on run 3 — the
                stamp has to be written before the tail or a crash
                loses it. The ? became an answer by being asked
                three times rather than by being thought about.
                Step 6 did not appear on run 3 at all.

TRANSLATE       Rows handed over. Told it: 2, 3 and 5 are load-bearing
                and in that order; 1, 4 and 6 are mine. On missing
                input — an empty find is normal and exits quiet, a
                failed convert stops everything and says so. It stops
                before the archive move; deciding what is worth keeping
                is not its business.

THE DIVERGENCE  The script archives in one move; by hand I always
                looked at the output directory first and twice that
                month I did not move something. That look was not a
                step on any of the three sheets, because I never
                thought of it as one. It is the only real finding here.
```

The divergence is a step that was on no sheet. That is the ordinary result and it is why the last move exists: three careful records of your own procedure will still miss the thing you do without noticing, and only running the automated version against the real task surfaces it.

---

## How to use it

1. **Fill the sheet in while you are working, not afterwards.** A step reconstructed from memory arrives already tidied, and the tidying is exactly the information this exists to keep.
2. **Do not read the previous sheet before the next run.** Reading it turns run two into a check of run one, and you will reproduce your own order rather than record it.
3. **Leave the question marks alone.** They are not gaps to be filled in later by thinking; they are answered by the third run or they stay unanswered honestly.
4. **Annotate what comes back, one comment per step.** This is the only defence against fluent code making an accident look like a reason.
5. **Do the divergence run.** Skipping it leaves you with a script and a story about a script, and the story is the part that was already tidied.

---

## Three ways it goes wrong

**The sheet is filled in at the end of the day.** It looks identical to one filled in at the desk, it is faster to produce, and every hesitation has been removed from it. This is the failure, and the question-mark column is the only place it shows: a completed sheet with no question marks on a first run has almost certainly been written from memory.

**The three runs happen on one afternoon.** Three runs an hour apart are one run recorded three times. The interval is doing work — you need to have forgotten the previous ordering, and a day is roughly what that takes.

**The translation is a description rather than the rows.** Pasting *it checks the feed, then finds new files, then converts them* gets you a script built from your summary, which is the tidied version arriving by another route. Hand over the sheet, including the accidents and including the blanks.

---

*Prayas Abhinav. Licensed [CC BY 4.0](https://creativecommons.org/licenses/by/4.0/) — copy it, change it, build on it, including commercially. Say where it came from, and if you changed it.*
