The Server Lives on Seoul Time
Every clock the engine reads is the office's, and the office keeps KST. Each turn's message opens with a line like [Current time: Monday, January 05, 2026, 09:30 PM KST]. Most of the year that is Dad's time too. When he travels, it is not.
For a while nothing else was said, and the model was left to convert. It did, and got it wrong: it read Dad's evening abroad as Seoul's night and answered for an hour he was not living. The arithmetic is not beyond a model. The model did not know which zone to convert to, and guessing the zone was the whole failure.
A Device Says Where Its Clock Is
So every device doorway reports its own. The Pippa app sends device_timezone with every turn and every location report; the WebUI sends it with every turn. It is meant to be an IANA zone name, never an offset or an abbreviation: America/New_York, not -05:00. The check at the door is a character pattern plus a lookup in the zone database, which turns away offsets and most abbreviations (CEST, KST). It is a filter, not a proof: a few legacy names still live in the database and pass, EST among them. There EST is a fixed UTC-5 with no daylight saving, so a client that sent it would get New York wrong for half the year, the very mistake a zone name exists to avoid. The location layer keeps the latest report from each device with the moment it arrived. Only Dad's own session moves his clock, and a private turn's zone is not kept at all. It does not even serve that turn: the routes drop what the check returns, and the time line is always built from the stored clocks.
Which Clock Wins
| Rule | Why |
|---|---|
| A report older than 7 days is ignored | it says nothing about where he is now |
| A phone report from the last 24 hours outranks everything else | a browser on the office Mac, reached by screen share from abroad, says Seoul while he is away |
| Otherwise the newest report wins | the freshest word stands until a fresher one arrives |
"Phone" means the devices that travel in his pocket or on his wrist: the Pippa app and its watch, plus a few family apps the engine counts as phone reporters (Pathfinder, Waystone, Spark, Vesta).
The Line Under the KST Line
When the chosen zone keeps a different time from KST right now, a second line follows the first: Dad's local time, the zone, which device reported it and how long ago, and an instruction to use it for anything about his day, his evening or "now" where he is, because the KST line is the server's clock, not his. When the zone keeps KST's offset there is no second line; the first already says it. Both lines ride the current user message, lesson 2's slot, because they change every minute. (The one small exception is the lightweight prompt for small local models, which still trails its clock at the end of its own short system text.)
Server-side doorways report no clock at all: Telegram, the scheduler, a sibling engine asking on Dad's behalf. They read the latest stored one. A Telegram message sent from abroad still gets Dad's local time, because his phone said so recently.
A Sentence That Went Stale
One honest footnote. The docstring of the system-prompt builder still says the current-time line is "prepended fresh on every call", a sentence from the days when the clock lived in the system prompt. The same docstring's contract paragraph, and the code, put it on the user message. Trust the code; that sentence is stale. Docs drift the moment a mechanism moves, and the only defense is someone reading both.