Flow
What each part does with a mislabelled record
1Old receipts
Ones saved correctly replay as before; mislabelled ones ask for review
2Planning
Stops with a clear review-needed error that names the shape
3New apply
Needs a person to review a fresh profile first
Three different kinds of record in my order planner were all wearing the same version label. The code that reads them picks its rules by that label, so it had no way to tell them apart.
Why the label matters
Some suppliers only sell whole cases. My planner buys the cases and then splits the units between stores, using a policy a person reviewed. Each step after that is saved and hashed. The hash is how I prove the plan came from the reviewed policy. That only works if a label always means the same shape.
How it drifted
Every time the planner learned something new, like a shared capacity limit or a rule for leftovers, the new fields went into the version-one schema. The label never changed. So the same label ended up on three different shapes. An old record might be rejected, or it might be read with blanks filled in by defaults. Those blanks decide how much gets bought. A default there is a buying decision nobody made. I should have caught it the first time.
The saved receipts can't be edited, so the repair had to happen when records are read.
Putting version one back
I put version one back exactly as it was first shipped. All the new fields moved to version two. The plan, profile and receipt got new versions too, and the hashes now include the version. One number had also changed meaning without a rename. It used to count days of stock after one pool and now counts after the whole plan. The new version keeps both, with names that say which is which.
For the records already saved with the wrong label, I didn't fix them in place. A small checker names each bad shape and returns only that name. Then each part of the system decides what to do:
- Old receipts that were saved correctly still replay as before.
- Planning stops with a clear review-needed error that names the shape.
- A new apply needs a person to review a fresh profile first.
Before this, a profile that failed to load just meant the report ran without it. Now it says why it stopped.
The tests run in both directions: old readers reject new records, new readers reject old ones, and the checker never hands back a repaired record.