~18 min · capstone, capability-design, key-design, shared-ownership, testing
Level 0Idle Hands
0 XP0/39 lessons0/12 achievements
0/100 XP to next level100 XP to go0% complete
"A good root is one where adding a child touches nothing else." — this quest, track 1
The Brief
Tinker today has one capability. This capstone designs a second one on paper, against the bill from track 2, to see whether the root really holds. The candidate is hypothetical — Tinker does not ship it — and deliberately small: set the system output volume for a preset and put it back afterwards. An editing session might want speakers at a fixed reference level; a broadcast might want them silent so nothing leaks into the microphone.
Paying the Bill, Line by Line
Parsing. Input is a target level from 0 to 1. initialInput is 0.5; validate refuses anything outside the range. Permission. Changing output volume needs no Accessibility, so the permission set is empty — which means this child would still work on a Mac where Dad has not granted Accessibility. Change.prepare reads the current default output device and its current level, and emits one plan whose payload carries the device's stable UID, the previous level and the target; needsApply is false when the device is already at the target. Apply re-reads just before acting: if the default device changed (headphones were unplugged), it throws ChangeNotAttempted. It sets the level, then confirms by reading it back. Undo sets the previous level only if the device still exists and its level is still the target; if Dad has turned the volume since, the answer is .noLongerApplicable — a manual change wins, exactly as a manual show did.
The Interesting Part: the Key
Track 3 showed that two presets touching the same thing share one receipt. That works for hiding because "hidden" is a single state. Volume is not. If the key is just the device UID, a broadcast preset that wants 0.0 applied while editing holds the device at 0.6 would find the editing receipt and merely join its owners — and the speakers would stay at 0.6. If the key includes the target, there are two receipts for one device, and undoing them in the wrong order restores the wrong "previous" level. There is no free answer; the engine's sharing rule is a property of the key the child chooses. A defensible design keys by device UID and refuses when a different target already holds that device — a standing refusal, known before any receipt, with a message that names the preset holding it. But notice who knows that another receipt holds the device: the journal, which a child never sees. Making the refusal possible takes one small addition to the root, and the exercise asks you to place it.
What Did Not Change
Set that one question aside and count the files the new child would touch: one new class, one adapter protocol and its system implementation, one line where the app registers its capabilities, and tests. The engine, journal, commands, hotkeys, links, the app door, Quit and logout handling all work untouched — the new child appears in Settings with a command and a tinker://command/audio.output-volume link before any UI is written for it. That is the test the root was built to pass.
Code
A hypothetical second child (not shipped in Tinker)·swift
import CwkKitCore
import Foundation
struct VolumeInput: Codable { var level: Double }
struct VolumeChange: Codable { var deviceUID: String; var previous: Double; var target: Double; var name: String }
@MainActor
protocol OutputVolume {
func defaultDevice() -> (uid: String, name: String)?
func level(of uid: String) -> Double? // nil: device gone
func setLevel(_ value: Double, of uid: String) throws
}
@MainActor
final class SetOutputVolume: Capability {
private let audio: any OutputVolume
init(audio: any OutputVolume) {
self.audio = audio
super.init(id: "audio.output-volume", name: "Set output volume", permissions: [])
}
override var initialInput: JSONValue { .object(["level": .number(0.5)]) }
override func validate(_ input: JSONValue) throws {
let level = try decodeValue(VolumeInput.self, input).level
guard (0...1).contains(level) else { throw TinkerError("Volume must be between 0 and 1.") }
}
override func prepare(_ input: JSONValue) throws -> [ChangePlan] {
try validate(input)
let target = try decodeValue(VolumeInput.self, input).level
guard let device = audio.defaultDevice(), let now = audio.level(of: device.uid) else {
throw TinkerError("No output device is available.")
}
let change = VolumeChange(deviceUID: device.uid, previous: now, target: target, name: device.name)
return [ChangePlan(key: "audio:\(device.uid)", payload: try jsonValue(change),
needsApply: abs(now - target) > 0.001)]
}
override func apply(_ payload: JSONValue) async throws {
let change = try decodeValue(VolumeChange.self, payload)
guard audio.defaultDevice()?.uid == change.deviceUID else {
throw ChangeNotAttempted("\(change.name) is no longer the output device; volume was left alone.")
}
try audio.setLevel(change.target, of: change.deviceUID)
guard let read = audio.level(of: change.deviceUID), abs(read - change.target) < 0.01 else {
throw TinkerError("\(change.name) did not confirm the new volume.") // uncertain
}
}
override func undo(_ payload: JSONValue) async throws -> UndoResult {
let change = try decodeValue(VolumeChange.self, payload)
guard let now = audio.level(of: change.deviceUID), abs(now - change.target) < 0.01 else {
return .noLongerApplicable // gone, or Dad moved the slider
}
try audio.setLevel(change.previous, of: change.deviceUID)
return .restored
}
}
The one line that changes in the app·swift
capabilities = [
HideApplications(applications: SystemApplicationVisibility()),
SetOutputVolume(audio: SystemOutputVolume()), // the second child
]
The key decides how presets share·text
key = "audio:<uid>" edit holds 0.6; broadcast wants 0.0
-> broadcast JOINS edit's receipt; speakers stay 0.6 (wrong)
key = "audio:<uid>:<target>" two receipts for one device
-> undo order decides which 'previous' wins (fragile)
key = "audio:<uid>" + refusal prepare refuses while another target holds the device
-> clear message, no receipt, Dad decides (defensible)
External links
Exercise
Finish the design. Write the fake OutputVolume for tests and list the five tests you would write first, each named for the guarantee it proves. Then implement the 'refuse while another target holds the device' rule: where in prepare does it go, how does the child learn that another receipt holds the device, and is that knowledge the child's or the engine's?
Hint
Tests: already-at-target is never acquired; device switched before apply leaves no receipt; failed read-back leaves an uncertain receipt; a manual slider change makes undo noLongerApplicable; a second preset with a different target is refused before any write. The holding knowledge lives in the journal, which the child cannot see — so either the engine passes the existing receipt's payload into prepare, or the engine itself compares payloads on a key collision. That is a real change to the root, and noticing it is the point of the exercise: the bill sometimes reveals a line the root has not printed yet.
Progress
Progress is local-only — sign in to sync across devices.