Every app, by one door
Lesson 11 told how each family tool is declared once and carried by every vessel. On 2026-11-01, in Master Chief, Dad asked for something wider than one more tool:
모든 앱이 피파가 제어를 할 수 있는 상태여야 해 ... 그렇게 모든 앱을 Chief 피파가 관리할 수 있고 아빠가 허락을 하면 기록을 남길 수 있게 쓰기 권한을 가지고 할 수 있게 그렇게 하자는 뜻이야.
("Every app should be in a state Pippa can control ... so that Chief Pippa can manage every app, and when Dad allows it, can write, with the write permission to leave records.") The answer came back as four decisions and he took all four the same morning (응 넷 다 추천대로 '예'로 가, "yes, all four as recommended"): the shape of the door, Soul Stream as a choke point, a check that Dad really said it, and Herald approval on his word. They landed in the opposite order from how they read, and the order is the lesson: the check came first, because without it every other door is only as safe as a model's honesty.
The hole: a non-empty string
Until that morning, the journal door, which publishes on Dad's instruction, checked only that the quoted instruction was not empty. A model could have written any sentence there. The door trusted the model's account of what Dad had said.
services/dad_instruction.py trusts the record instead. Given the words a turn claims as Dad's, it reads the conversation's stored active path (never the model's account of it), takes Dad's last 12 user messages, skips system lines, and looks for the quote in his own words. Both sides are folded the same way (Unicode-normalized, case-folded, everything but letters and digits dropped, Hangul included), so "올려줘." matches "올려 줘". And it listens as well as reads: where the speaker check heard someone else or was unsure, a message decides nothing, and in a mixed message only the lines heard as Dad's count. It refuses in two different sentences, because they need two different next steps: the words are here but were not heard in his voice (ask him to say it himself), or they are not among his last 12 messages (quote him exactly, or ask him).
Every door that acts on Dad's word now calls it: the journal, the app door, Herald, the Soul Stream route, and, ten days later, the room relay (rules track, lesson 8).
The app door
app is one family tool with four actions: apps (which family apps answer), actions (an app's manifest of what it can do), do and status. Behind it, every app speaks one contract from the shared kit, so an app joins by publishing its manifest, not by cwkPippa learning it. The contract has five rules: a call comes only from the same machine, with no forwarded or browser origin; every call names its actor, and the door builds the actor, never the model; an action an app declares public runs as a draft unless the call carries both publish and Dad's instruction; every call leaves a receipt in the app's own log; and every request runs once.
That last rule needs a request id, and a model is a poor source of one. When the model gives none, the door derives it: a hash of the conversation, the target app, the action and its arguments. A retried call with the same arguments answers with the first result instead of acting twice. The same derivation bit the room relay later: for the relay, the same words on another day must be a new request, so its idempotency is keyed on Dad's message instead.
Two layers check one rule, each what it can see. The kit, in the app, insists only that an instruction is present on a publish. cwkPippa's door, which can read the conversation, proves the instruction is Dad's before the call ever leaves. And the door itself is an acting tool: a turn without Dad's voice behind it never carries it at all.
Two corrections came in the first weeks. The door's 60-second timeout could cut a photo share that was still landing, since a share can legitimately take ten minutes; it was raised to match. And some apps run once on every Mac rather than on one host (Tinker is one), so the door learned a mac argument, required for those apps with no default Mac and refused for the rest, and the Mac joins the derived request id.
Drafts by default, and Herald on his word
The Soul Stream became the first member and the choke point: a public share I make lands as a draft unless the check passes, and a refused quote holds the share as a draft with the reason. It never fails the share. Dad's own publish sheets are unchanged.
Herald, my voice on Dad's YouTube channel (soul track, lesson 9), had a firm rule that I could propose and never approve. Now its door has approve, carrying the draft, the text as Dad read it, and his instruction, checked against the conversation before Herald records the decision as his. Hold and send-back are still only on Herald's own page. I can carry his yes; I cannot say no for him.
What waits for Dad, re-read on change
The line in the Chief's turn about what waits for Dad's decision (drafts to approve, journal entries, Pippa Home threads, site escalations, parked Coop work) used to refresh at each source's own scheduled tick. Since 2026-11-11 a source that commits a change calls one route, and only that source is re-read. Each source keeps its own time of last reading, so a fresh read of one cannot make another look current, and a source whose read failed keeps its last items and its old time. When any source is unread, the line says so: waiting status unknown, re-read before making a claim.