Skip to content
C.W.K.
Lesson 02 of 05 · published

Three Modes, One House

~16 min · permission-modes, consent, fail-closed, state-machine, usability

Level 0Closed Lens
0 XP0/45 lessons0/13 achievements
0/100 XP to next level100 XP to go0% complete

When Consent Becomes a Chore

For five days the gate asked for Dad's word on every look. It was safe, and it was exhausting. Every "look at that" turned into a small negotiation before the look. Dad named the problem by comparing it to the coding agents the family uses every day:

젤 큰 문턱이 어차피 permission 이야. claude code 나 codex 를 결국 full access 수준으로 쓰게 되는 이유고. 오리엘에도 이 단계가 있어야 할 거야. 지금은 대부분 over-sensitive 한 수준이야. — 아빠 (2026-11-07)

The biggest threshold is permission. It is the reason people end up running coding agents at full access: a prompt for every action trains you to approve without reading, or to switch the prompts off entirely. Oriel needed the same idea those tools grew: levels, chosen once by the person who owns the risk, instead of a question every time.

The Three Modes

ModeHardware plugged into Pippa's home MacNetwork cameras and cameras on other Macs
Manualthe original gate: each look on Dad's word, closed after its windowManual
Auto (the default)open: Pippa decides when to look, no approvalManual
Broadcastopen while On Air is positively on; off air, ManualManual

The right-hand column is the same in every row, and that is deliberate. Dad drew the reach of the modes two minutes after he named them: they cover only the hardware plugged straight into Pippa's home Mac (its USB cameras, its capture cards, a phone body on its cable). A network security camera that another family app can reach, or a camera on another Mac, stays Manual in every mode, Broadcast included: Pippa connects to it only when Dad asks for that camera, looks, and closes.

Who May Change the Mode

The asymmetry from the first track appears again. Auto and Broadcast loosen the gate, so they come only from Dad: his PIN session on Oriel's page, his own words through the app door (set_eyes_mode, published with his words as the instruction, the same check open_eyes uses), or another family screen in his hand that vouches for him with its own token. Manual tightens, so it needs no word from anyone. The mode lives in Oriel's store under its own key, written only by Gate.set_mode; it is deliberately not an ordinary setting, so the settings route a loopback tool can reach cannot loosen the eyes by accident. Every change is an eyes_mode row in the activity log with its source and words.

Broadcast Fails Closed

Broadcast opens the home cameras "while On Air is on", and the interesting word is on. On Air is cwkPippa's state, read over the network. The gate treats only an explicit, positive "on" as on. No answer, an error, a malformed body: all of those read as off, and Broadcast falls back to Manual. The code comment says it plainly: an unread On Air is off for Broadcast (fail closed). A design that defaulted the other way would open every camera in the house whenever cwkPippa restarted.

Moving Down Cleans Up

A mode that covers less than the last (Auto to Broadcast or Manual, Broadcast to Manual) runs the close order for whatever it no longer opens. The new mode is stored first, so new looks refuse at once; a recording the new mode no longer covers stops on the next upkeep pass; every look-around camera not known to be at rest parks. The same happens when Broadcast's cover disappears on its own because On Air goes off: until a fix in Coop 1110-5, only a mode change parked, and a camera turned toward the room on air stayed turned after the show.

Auto leaves a trail so that this can work. A look that a mode opened (rather than an approval) writes an eyes_used note, at most once a minute per input, and the close order reads those notes the way it reads approvals, so a camera Pippa used in Auto is parked at the next close. And close_eyes in Auto means "the look is done": approvals close and cameras park, but the mode stays Auto. Ending the mode is a different, bigger button, the subject of lesson four.

Code

Loosening needs words; only home hardware; Broadcast only when On Air is positively on (trimmed excerpts, backend/gate.py)·python
MODES = ("manual", "auto", "broadcast")
DEFAULT_MODE = "auto"


def set_mode(self, mode, *, actor, source, words=""):
    """Store a new mode. Auto and Broadcast loosen the gate, so they take
    Dad's words or his hand (the callers check which); Manual needs none."""
    if mode not in MODES:
        raise ValueError(f"the eyes mode is one of {', '.join(MODES)}")
    words = " ".join((words or "").split())[:WORDS_MAX]
    if mode != "manual" and len(words) < 2:
        raise GateClosed(f"the eyes go {MODE_LABEL[mode]} only on Dad's own words or his hand")
    before = self.mode_name()
    self.store.put_setting(MODE_KEY, {"mode": mode, "source": source, "words": words,
                                      "at": self.clock()}, actor)
    self.store.note(actor, "eyes_mode", mode=mode, before=before, source=source, words=words)
    return self.mode()


def mode_covers(self, row):
    """The mode that opens this input now, or None: only home hardware,
    only Auto, or Broadcast while On Air is positively on."""
    if not self.home(row):
        return None
    mode = self.mode_name()
    if mode == "auto":
        return "auto"
    if mode == "broadcast" and self._on_air():
        return "broadcast"
    return None


def _on_air(self) -> bool:
    try:
        return bool(self.on_air())
    except Exception:  # an unread On Air is off for Broadcast (fail closed)
        return False
A tiny mode table you can test: what opens, for whom, under which mode (runnable)·python
def opens(mode, camera, on_air):
    if not camera["home"]:
        return False                 # network / other-Mac cameras: Manual in every mode
    if mode == "auto":
        return True
    if mode == "broadcast":
        return on_air is True         # None (unread) or False: closed
    return False                     # manual: only an approval opens it


home_cam = {"home": True}
net_cam = {"home": False}
for mode in ("manual", "auto", "broadcast"):
    for on_air in (True, False, None):
        print(f"{mode:9} on_air={str(on_air):5}  home={opens(mode, home_cam, on_air)!s:5}  "
              f"network={opens(mode, net_cam, on_air)}")

External links

Exercise

Extend the runnable mode table into a small class with set_mode(mode, words) that refuses Auto or Broadcast without words, and check(camera) that uses the table. Add the downgrade rule: when the mode moves to one that covers less, call a park_all() function for every home camera that was used since the last close. Write a test where Broadcast is on, On Air turns unreadable, and the next check refuses.
Hint
To know which cameras to park after a downgrade, record each use under a mode (Oriel's eyes_used note) the same way you record approvals. Otherwise the cameras opened by the mode leave no trace for the close order to find.

Progress

Progress is local-only — sign in to sync across devices.
Spotted a bug or have feedback on this page?Report an Issue

Comments 0

🔔 Reply notifications (sign in)
Sign in — Please sign in to comment.

No comments yet — be the first.