A change you can read.
Ask an automation team what changed in the machine program last Thursday and the honest answer is usually a shrug, a folder of dated archives, and someone opening two copies side by side to compare them by eye.
It is not for lack of discipline. It is that the project was one opaque file. You cannot diff an opaque file, so you cannot review it, cannot merge it, and cannot say with confidence what is running on the machine.
A project is a folder, not a file
And the folder has the same shape as the machine.
Save a StateTick project and you get a directory. Inside it, every authored thing is its own plain text file, in a folder named for what it is, under a filename that is the entity’s own name.
States sit in states. Conditions sit in conditions. Equipment, interfaces, logic blocks, alarms, composites and machines each have their own. Fieldbus work lives apart from the logic, because it is a different concern.
Nothing about this is a special export or a sidecar copy that has to be kept in step. It is simply how a project is saved and opened. There is no “now generate the version-controllable form” step to forget.
And it is not tied to any one tool. These are ordinary files in ordinary folders. Git, Subversion, Perforce, your company’s document system, or a dated copy on a server — they all work, because none of them need to understand the format to store it.
The diff shows what you did
Which requires the file to be written the same way every time.
Splitting a project into files is only half of it. If the contents shuffle between saves, every save still looks like a rewrite and the diff is noise.
So everything is written in a fixed order — entities sorted by name, the same layout, the same formatting on every save. Save a project twice without touching anything and nothing changes on disk. Change one guard expression and the record of that change is this:
{
"id": "f60465d9-0a41-4bc6-9ae2-a0f6df00f2dc",
"name": "CappingCtrl_IsCappingDone",
- "expression": "CapperDown AND TorqueOK"
+ "expression": "CapperDown AND TorqueOK AND NOT Fault"
}
That is the entire change set. Not a rewritten project, not a binary that reports only “differs” — one line, with the old value next to the new one, attached to a name that says what it belongs to.
Which means the ordinary habits of software finally apply to a machine. You can review a change before it reaches the plant. You can see who made it and read why. You can go back to exactly the version that was running in March, not the archive somebody remembered to take in March.
Most platforms do offer a compare tool, and they are genuinely useful. The difference is where the comparison lives: a built-in compare answers “how do these two copies differ” when you go looking, whereas plain text in version control answers “what has happened to this machine, and why” as a matter of record — using whatever your organisation already uses for everything else it builds.
Two engineers on the same machine
The part that is usually impossible, and why the file layout is what makes it work.
Commissioning weeks are the test. One engineer is fixing the capper on site. Another is building out the outfeed from the office. Traditionally this ends one of two ways: they take turns, or they merge by hand at midnight and hope.
Because each entity is its own file, most of that conflict simply never arises. Two people working on different parts of the machine are writing to different files, and the merge is arithmetic rather than judgement.
This is the quiet consequence of the naming scheme described elsewhere on this blog: because a state, a condition and a piece of equipment are separate named objects rather than regions of one program, they are separable on disk too. The structure that makes the machine readable is the same structure that makes it mergeable.
A branch is a machine variant. Once the project is text, the things software teams do become available without ceremony: a branch for the customer-specific option, a branch for next season’s recipe changes, a tag for what shipped. Bring them together when they are ready, with a record of what came from where.
Keeping the folder honest
A history is only worth having if it cannot quietly drift from reality.
Two things could spoil that, and both are handled when the project is written.
The first is leftovers. Delete a condition and its file is removed, not orphaned. Empty the test suite and the suite file goes with it. A folder that keeps stale files around is a folder that lies to you a year later, when someone finds a state nothing references and cannot tell whether it matters.
The second is provenance. Alongside the project sits a small record of what it is: the name, when it was created, when it was last saved, which version of the software wrote it, a format version so older projects keep opening, and a fingerprint of the authored content. When a project arrives from a colleague or comes back off a branch, that record travels with it.
What travels with the project
- Everything authored: logic, equipment, alarms, machines.
- The fieldbus mapping, kept apart from the logic.
- The reusable templates and the machine plan.
- The test suite, so a clone can prove itself.
What stays a local matter
- Per-machine preferences, kept in their own place.
- Deployment target settings, separable from the project.
- Any credentials involved are encrypted, never stored as readable text.
Where exactly that line falls is your team’s call, not something the software decides quietly on your behalf. Everything is written out, and you choose what to leave untracked — because sharing a little too much costs you some noise in a diff, while sharing too little costs a colleague a project that opens with something missing.
What this is really for
Not tidiness. Answers.
Questions that get answers
- What changed since the machine passed acceptance?
- Who changed this guard, when, and what did they say about it?
- Is what is running the same as what we signed off?
- Can we get back to the version from before the shutdown?
Habits that become possible
- Reviewing a change before it reaches a live machine.
- Two engineers working the same week without taking turns.
- A branch per customer variant, merged when it is ready.
- A tag that means exactly what shipped.
The machine program stops being an artefact and starts being a codebase.
None of this is exotic. Every other discipline on the project already works this way: the drawings have revisions, the mechanical model has a history, the documentation has an owner and a date. Automation was the outlier, and mostly because of the file format.
Change the format and the rest follows on its own. A project that is a folder of small, ordered, plainly-named text files can be diffed, reviewed, merged, branched, restored and audited — using whatever your organisation already trusts to do those things. StateTick’s part is simply to store the machine in a shape those tools can read.
Machine Paths, Not Scattered Tags — the naming and structure that make separate files possible in the first place.
The Test Manager — the other half of reviewing a change: proving it still does what it did before.