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

Pippa Names the Mac — and Has No Resume Button

~13 min · per-mac, forwarding, manifest, paged-reads, no-resume

Level 0Idle Hands
0 XP0/39 lessons0/12 achievements
0/100 XP to next level100 XP to go0% complete
"Her app door takes mac, a fleet label from the registry's enrollment, and never picks a Mac by itself." — Tinker README

Reaching a Door on Another Mac

Tinker's door listens only on loopback, so how does Pippa, whose own service runs on another Mac, reach it? Through the family's control route. Her app door, asked to call a per-Mac member on a named Mac, opens a forward over the family's command channel that ends at that Mac's loopback port. On her side the forward is a Unix socket named for the Mac, because every Tinker uses the same port number and a numbered local port would not say which Mac it leads to. On Tinker's side the request arrives from 127.0.0.1, possibly with the forward's port in Host — which is exactly the case the listener's allow-list admits.

The Port Comes From the Registry

Tinker never hard-codes its port. At startup the agent asks its worker for it, and the worker reads Tinker's entry from the vendored family registry — the per-Mac table, where an @each claim gives every enrolled Mac the same number. Pippa's side reads the same registry. If the two ever disagreed, the listener simply would not be where she looks, which is a loud failure, not a silent one.

What Pippa Can Ask For

The manifest at GET /api/app-actions lists every action with its schema, effect and a sentence about what it reads. Reads: status, preset.list, preset.get, command.list, change.list and activity.list. Writes that set a value: preset.save and binding.set. A delete: preset.delete. Executions, each needing a request ID: preset.apply, preset.restore, preset.toggle, command.run and release. preset.save is described as "Save a preset and its bindable commands; never runs it." — saving and running are different requests on purpose.

Small Answers, Paged Lists

Every answer lands in a model's context, so the kit caps its size and drops data that grows past the limit. status is deliberately compact — permission, stopped, busy, the active owners, counts of owned and uncertain changes, hotkey errors, the status line and the last Watchfire observation. The lists that can grow are their own actions and answer page by page with an after cursor. An answer cut silently at a size limit would look like a short list; a paged one cannot.

No Resume Action, on Purpose

Look at what is absent: there is a release but no resume. Pippa can always stop Tinker and restore everything — that direction only ever makes the screen more like Dad left it. She cannot undo a stop. Resuming after an emergency, or after an uncertain record was resolved, is a decision about whether it is safe to act again, and it is Dad's, made from the menu or Settings. The README puts it in one line: "There is no resume action: only Dad resumes after a stop."

Code

The worker's answer to 'which port am I?' (from bridge/worker.py)·python
import kit_family_endpoints as family

def port_answer():
    data = (family.FAMILY_SERVICES.get('cwkTinker')
            or family.FAMILY_PER_MACHINE.get('cwkTinker'))
    if not data:
        raise ValueError('Tinker is missing from the family port registry.')
    return {'port': data['engine']}
What reaches the named Mac's door: POST /api/app-actions/preset.apply (illustrative body)·json
{
  "actor": {"kind": "pippa", "brain": "<brain label>"},
  "request_id": "<unique per deliberate request>",
  "args": {"id": "edit"}
}
Reading every page of a growing list with the kit helper·python
from kit_app_actions import collect_pages

def all_changes(call):
    """call(after) performs one change.list request and returns its answer data."""
    return collect_pages(lambda after: call({"after": after} if after else {}))

# Each item: {"id", "name", "capability", "phase", "owners", ["error"]}

External links

Exercise

Pippa notices the editing preset is still active an hour after Dad's session ended, on the video Mac. Write the sequence of door requests she should make — reads first — to confirm and fix it, including request IDs where needed. Then describe what she should do if change.list shows one uncertain record.
Hint
status (and change.list) on the named Mac to confirm edit is active and what it holds; then preset.restore with args {"id":"edit"} and a fresh request_id; then status again. If an uncertain record remains, restore will not touch it and she cannot Forget it or resume through the door — she tells Dad which app is uncertain and leaves the decision to him in Recovery.

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.