Flow
Where the list gets converted
1Staff page
Turns digit text into numbers before sending. Not needed, and the one that broke.
2Server on save
Cleans the list and stores numbers as numbers.
3Server on read
Cleans the list again, so old records come out tidy.
4Scheduler
Checks both the ID and the old name, so old and new records both work.
For part of one afternoon, the store-admin staff editor in my app couldn't save anyone who had a favorite chore. Select a chore, press save, and the page threw an error before it sent anything to the server. I found this by reading the day's changes, not by watching it fail.
How preferences feed the scheduler
My scheduling app for the stores prints each day's schedule with chores attached to the people working. Staff can list the chores they would rather do. The scheduler first works out who is allowed to take a chore, then picks among the people who asked for it, or among everyone allowed if nobody asked. A preference only ever breaks a tie.
Preferences used to be stored as the chore's text. That's a bad key, because text is exactly what people edit. Change a chore's wording and every old preference stops matching, with no error anywhere. The chore still gets assigned, just to someone who didn't ask for it.
Names out, IDs in
Around midday the agent switched preferences to chore ID numbers. The dropdown now sends each chore's ID and shows its name, and it hides chores that are archived or can't be assigned automatically. A saved preference that no longer matches anything still appears as an unavailable entry, so saving the form doesn't wipe it out.
The hard part is that the list now arrives in mixed shapes. Older records hold text, newer records hold numbers, and a browser dropdown always returns text, so chore 12 arrives as "12". The change therefore cleans the list in three places: the server tidies it on every read and save, the scheduler checks both IDs and old names, and each staff page converts digit-only text into numbers before sending.
One pattern, declared in the wrong room
That last step broke one page. The pattern that recognizes digit-only text was declared inside one function, and the helper that reads the dropdown lived outside that function, so it couldn't see the pattern. With nothing selected, the pattern was never used. Select one chore and the save failed. The other staff page declared the pattern in the right place, and the two pages looked so similar that I merged the change without noticing.
The step wasn't even necessary. The server and the scheduler already convert "12" into 12 on their own.
Rescued by a branch that wasn't looking
About an hour and a half later I merged a different agent branch, which added the pattern at the top of that page, and saving worked again. That branch was started before the ID change existed, so I doubt it was meant to fix this. My best guess is that it was luck.
The rules nobody has pinned down
No tests came with this change. On the server, a stray true value becomes chore 1, a decimal gets chopped to a whole number, and a chore whose name is only digits would be read as an ID. Those rules deserve tests, not a careful read of the code every time.