Der Mixer gibt den Ton der bearbeiteten Programme selbst aus — und steht damit
als Tonquelle in seiner eigenen Liste. Eine Zeile wird geregelt, sobald man ihren
Regler anfasst. Ein Klick auf Onyx' eigene Zeile genügte also.
Der Selbst-Tap läuft wie jeder andere mit mutedWhenTapped und schaltet damit
Onyx' gesamte Ausgabe stumm — die Wiedergabe *aller* bearbeiteten Programme.
Völlige Stille, während die Pegelanzeigen weiter ausschlagen, weil die Taps ja
Signal bekommen. Und der Zustand stand in den Einstellungen, überlebte also
jeden Neustart.
Gemessen (Spikes/mixer-path-probe.swift): Onyx' Ausgabepegel klettert von 0,388
auf 2,833, sobald er sich selbst bearbeitet. Der Weg an sich ist in Ordnung —
Tap, Aggregate-Gerät und IOProc liefern einzeln wie zu dritt volle Pegel, das
war der Hauptverdacht und ist widerlegt.
Onyx erscheint jetzt nicht mehr in der eigenen Liste, lässt sich nicht auswählen,
und ein gespeicherter Eintrag wird beim Laden entfernt und zurückgeschrieben.
Dazu ein zweiter Fund aus derselben Ecke: setVolume und setMuted griffen auf
taps[bundleID] zu. Die Taps liegen aber unter Kennung#Prozessnummer, weil ein
Programm mehrere Tonquellen haben kann — der Zugriff ging immer ins Leere. Der
Regler wirkte erst, wenn die Auffrischung drei Sekunden später nachzog.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Der Regler war eine Pseudobedienung. Der SMC lehnt Schreibzugriffe auf CHLT
ab — der Helfer hat es mit korrekter Größe versucht und „geschrieben (false),
zurückgelesen 85" gemeldet. Das Sicherheitsnetz hat also die Wahrheit gesagt;
die Oberfläche hat sie nur nicht gezeigt.
Weiter zu raten hieße, im Lade-Subsystem Keys durchzuprobieren, und das ist
die eine Operation in diesem Projekt, die Hardware dauerhaft beschädigen
kann. Also: das Limit wird gelesen und angezeigt, mit einem Weg in die
Systemeinstellungen, wo es tatsächlich geht. Der Schreibpfad ist aus dem
privilegierten Helfer entfernt — ein Root-Dienst trägt nur, was benutzt wird.
Die Akku-Kachel zeigte „40 %" und einen Verlauf über die letzten Sekunden.
Der Ladestand ändert sich in Minuten, nicht in Sekunden; der Graph war eine
waagerechte Linie. Jetzt: verbleibende Zeit bzw. Zeit bis voll, Leistung in
Watt mit Richtung, Ladelimit, Zustand, Zyklen — und der Energiesparmodus.
Der erklärt, warum die Maschine langsamer wirkt, und ohne diesen Hinweis
sucht man den Grund woanders.
In der Menüleiste standen fünf nackte Prozentzahlen nebeneinander. Man sah
Zahlen und wusste nicht, welche wozu gehört. Zwei neue Darstellungen: Kürzel
und Wert („CPU 34 %") sowie Symbol und Wert. Beim Akku stehen sie zuoberst in
der Auswahl.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
IOReport liefert je Kern die Verweilzeit in jeder Leistungsstufe, genau wie
gebraucht: MCPU00 bis MCPU14, 17 Zustände, saubere Deltas zwischen zwei
Messungen.
Die Frequenz zu einer Stufe steht dort aber nicht. Sie muss aus den
voltage-states-Tabellen im IODeviceTree kommen, und die passen nicht: der Kanal
hat 16 Leistungsstufen, keine Tabelle hat 16 Einträge. Dazu sind die Einheiten
uneinheitlich — voltage-states8 enthält echte Hertz (732–2472 MHz),
voltage-states5 dagegen Paare wie (50103, 635), die in keiner Einheit sinnvolle
Taktraten ergeben.
Ab hier wäre es Reverse Engineering undokumentierter Firmware-Tabellen, deren
Format sich zwischen Chip-Generationen ändert — genau die Sorte Code, die beim
nächsten Mac still falsche Zahlen anzeigt statt zu scheitern. Dafür ist eine
Zusatzangabe im Popover zu wenig, solange Phase 6 bis 9 offen sind.
Die halbfertige Implementierung ist entfernt statt auskommentiert: nicht
verdrahteter Code, der nil liefert, verrottet und täuscht später
Vollständigkeit vor. Der Stand samt Fortsetzungsweg steht in
docs/spikes/F-frequenz.md.
Die Ursache stand wörtlich im Protokoll von tccd:
Prompting policy for hardened runtime; service: kTCCServiceCalendar requires
entitlement com.apple.security.personal-information.calendars but it is missing
Bei aktivierter Hardened Runtime verlangt TCC diese Entitlements auch ohne
App-Sandbox. Die verbreitete Annahme, sie gälten nur für sandboxed Apps, ist
falsch — und ich bin ihr aufgesessen. Ohne sie zeigt macOS den Dialog gar nicht
erst an: die Anfrage kommt nach Millisekunden mit false zurück, der Status
bleibt notDetermined, und die App taucht in den Systemeinstellungen nie auf.
Dort lässt sich auch nichts nachtragen, der Kalenderbereich hat kein
Pluszeichen — eine Sackgasse ohne jede Fehlermeldung.
Gesetzt sind jetzt calendars, location, apple-events und audio-input, also
alles, was Phase 3, 4 und 7 brauchen. Sie fehlen sonst genau dann, wenn das
Feature fertig ist und niemand mehr an TCC denkt.
Gefunden durch Ausschluss, nicht durch Nachdenken: eine minimale Test-App
(normales Fenster, im Vordergrund, gleiches Zertifikat, nichts von Onyx darin)
scheiterte identisch. Damit war belegt, dass es nicht an Onyx lag.
Der Weg dorthin führte über mehrere falsche Fährten, die in
docs/spikes/E-tcc-hardened-runtime.md stehen, damit sie niemand zweimal geht —
darunter eine eigene: `log show` wurde von zsh abgefangen, und weil stderr
umgeleitet war, sah die leere Ausgabe wie ein Befund aus.
In der Praxis geprüft: Dialog erscheint, Zugriff erteilt, Status 3.
Vier Annahmen des Plans vor jedem Implementierungscode geprüft:
A (SMC): Lüftersteuerung bestätigt — F0md/F1md (klein!) als Auto/Manuell-
Umschalter, F0Tg als Ziel, Grenzen aus F0Mn/F0Mx. SMC-Integer sind
little-endian, nicht big-endian wie im verbreiteten Intel-Beispielcode.
Ladelimit: CHWA/CH0B/CH0C/bfE0/bfF0 existieren auf Mac17,9 nicht.
Key noch nicht identifiziert, deshalb smc-diff.sh für eine
Differenzmessung ohne jeden Schreibzugriff.
B (Media): mediaremote-adapter läuft unter 26.6.1, aus dem Quellcode gebaut.
Liefert vollständige Metadaten inkl. Cover aus Google Chrome — der
Fall, den AppleScript nicht erreicht.
C (Audio): Process Tap + privates Aggregate-Device liefern echte Samples
(469 Callbacks/5 s, 0 stille Puffer). Konflikt gefunden: SoundSource
6.1.1 mit ARK.driver ist bereits installiert.
D (Group): App-Group-Container ist aus einem nicht-sandboxed Prozess erreichbar.
Damit trägt die Sandbox-Entscheidung, die Bridge-App entfällt.
Spikes sind Wegwerfcode zur Verifikation, kein Produktionscode.