Skip to content

Configuration

Every tunable knob in the app, reading directly from YameteCore/Defaults.swift, YameteCore/Constants.swift, and YameteCore/ReactionsConfig.swift. The point of this page is to make the design legible: if a number lives in production code, it lives on this page with a sentence about why.

Response controls

User-facing surface in the menu bar dropdown. Clamped on every SettingsStore write.

SettingDefaultRangeWhat it does
Sensitivity (min / max)0.10 / 0.900.0…1.0Inverted threshold band. High sensitivity → low intensity threshold → more reactions fire. Below the band an impact is rejected silently. Above it intensity is remapped onto a clean 0…1 the rest of the system uses.
Volume (min / max)0.50 / 0.900.0…1.0Range randomly sampled per-clip so the same clip does not play at the same level twice in a row.
Flash opacity (min / max)0.50 / 0.900.0…1.0Range randomly sampled per overlay so successive flashes vary.
Sound enabledonboolMaster toggle for AudioPlayer. Per-event row in the matrix still applies.
Screen flash enabledonboolMaster toggle for ScreenFlash. Per-event row in the matrix still applies.
Visual response modeoverlayoff / overlay / notificationThree-way switch under Flash Mode.
Debug loggingoffboolDirect build only. Adds [DEBUG] lines to the file log; verbose.

Fusion / timing

Cross-sensor fusion lives in ImpactFusion. The values here are the contract between three parallel ImpactDetector streams.

SettingDefaultRangeWhat it does
Consensus11…10How many impact sensors must agree inside the fusion window for the fused impact to publish. 1 means any single sensor wins. 2 forces at least two.
Debounce0.5 s0…2 sCooldown after a fused impact publishes. The bus rejects another fused impact in the same window.
Fusion window0.15 sconstantSliding consensus window. A second sensor's spike has to land inside this many seconds of the first to count as agreement.
Rearm duration0.50 sconstantAfter fusion fires, the engine ignores any further sensor agreement until this elapses. Difference between yelling once when you smack it and yelling four times because four sensors agreed within 200 ms.

Sensitivity gate math

FusedImpact.applySensitivity(rawIntensity:sensitivityMin:sensitivityMax:):

thresholdLow  = 1.0 - sensitivityMax
thresholdHigh = 1.0 - sensitivityMin
if rawIntensity < thresholdLow:
    return nil   // reject // below the user's reactivity floor
remapped = (rawIntensity - thresholdLow) / max(0.001, thresholdHigh - thresholdLow)
return clamp(remapped, 0…1)

Result: low sensitivityMin (default 0.10) → high thresholdHigh (0.90) → wide band → most impacts pass. High sensitivityMin → narrow band → only the loudest impacts pass.

Detection: accelerometer

BMI286 via IOKit HID through the SPU broker. Bandpass-filtered g-force.

SettingDefaultRangeWhat it does
Spike threshold0.020 g0.010…0.040Magnitude that has to be exceeded for the spike gate to fire. Lower is more reactive.
Crest factor1.51.0…5.0Ratio between peak and recent RMS. Filters sustained vibration (truck, fan) from sharp transients (smack).
Rise rate0.010 g/sample0.005…0.020Per-sample slope minimum. A slow ramp into threshold is rejected; sharp rises pass.
Confirmations31…5Number of consecutive samples that must hold above threshold. Cuts isolated noise.
Warmup samples5010…100Filter-settling burn-in period before the detector publishes anything.
Report interval10 000 µs5 000…50 000IOKit HID report cadence in microseconds. 10 000 µs = 100 Hz polling.
Bandpass low20 Hz10…25High-pass corner; cuts low-frequency drift (gravity, posture).
Bandpass high25 Hz10…25Low-pass corner; cuts high-frequency hash.
Intensity floor0.002 gconstBelow this the published intensity clamps to 0.
Intensity ceiling0.060 gconstAbove this the published intensity clamps to 1.

Detection: gyroscope

BMI286 angular velocity in deg/s. Same SPU broker, different HID usage (9 vs 3).

SettingDefaultRangeWhat it does
Spike threshold200 deg/s50…500Angular-velocity magnitude required to fire.
Crest factor2.51.5…5.0Peak-to-recent-RMS ratio. Filters sustained rotation (Mac picked up off a desk and walked) from sharp spikes (lid yank).
Rise rate50 deg/s/sample10…200Slope minimum.
Confirmations31…10Consecutive samples above threshold.
Warmup samples500…200Burn-in.
Intensity floor / ceiling50 / 500constMagnitude clamping for the 0…1 published intensity.

Detection: lid angle

Hinge angle in degrees via the dedicated lid HID device (Vendor 0x05AC, Product 0x8104, UsagePage 0x0020, Usage 0x008A), Feature Report 1 polled at 30 Hz. NOT on the SPU IMU stream — that channel carries no lid data at any offset. State-machine driven downstream of the decode.

Coverage: M2 Pro/Max, M3 family, and M4 family laptops have the device. M1 (any), M2 base MacBook Air, M2 base 13" MacBook Pro, and every desktop (Mac mini / Mac Studio / Mac Pro / iMac) do not surface lid angle — isAvailable returns false on those hosts and the menu toggle hides.

SettingDefaultRangeWhat it does
Open threshold10°5°…30°Angle above which the lid is considered open. Crossing from below fires lidOpened.
Closed threshold1°…10°Angle below which the lid is considered closed. Crossing from above fires lidClosed.
Slam rate-180 deg/s-500…-50Closing rate (negative. closing reduces angle). If the lid crosses the closed threshold faster than this the event is lidSlammed instead of lidClosed.
Smoothing window100 ms50…500EMA window over Δangle/Δt to suppress jitter.

Detection: ambient light

Lux via SPU HID usage 5. Two-second ring buffer + step detector.

Coverage: every Apple Silicon MacBook except the M1 13" MacBook Pro (2020). iMac is inferred to support it via the same channel. Mac mini, Mac Studio, and Mac Pro have no built-in display and no internal ALS; the menu toggle hides on those hosts. External displays (Studio Display, Pro Display XDR) carry their own ALS via AppleUSBALSService on UsagePage 0x0020 — that path is independent of this source.

SettingDefaultRangeWhat it does
Cover-drop threshold0.95 (95 %)0.5…0.99Fractional lux drop required to fire alsCovered (hand over the sensor).
Off-drop percent0.80 (80 %)0.5…0.99Fractional drop required to fire lightsOff (switch flipped).
Off-floor lux30 lux1…300Post-drop ceiling. lux must end below this for lightsOff to fire.
On-rise percent1.50 (150 %)0.5…5.0Fractional rise required to fire lightsOn.
On-ceiling lux100 lux50…1000Post-rise floor. lux must end above this for lightsOn to fire.
Window2.0 s0.5…10.0Ring-buffer duration the step detector compares before-and-after over.

Detection: thermal

ThermalSource observes NSProcessInfo.thermalStateDidChangeNotification. The state set, the transition gates, and the cadence are all OS-defined. The user-facing knob is the reactivity floor ratchet that gates which state transitions actually publish a Reaction.

SettingDefaultRangeWhat it does
Thermal reactivity floor20...40=off, 1=critical only, 2=serious+critical, 3=fair+serious+critical, 4=all states. The gate consults floorProvider from SettingsStore at publish time so live changes take effect immediately.

Cold-start suppression always applies: the initial state captured at start does not publish (otherwise launching Yamete on an already-warm Mac would always fire thermalFair). The floor gates ON TOP of the dedup, not in place of it.

Detection: microphone

High-pass-filtered PCM amplitude via AVAudioEngine.

SettingDefaultRangeWhat it does
Spike threshold0.0200.005…0.100Amplitude required to fire (post HP filter).
Crest factor1.51.0…5.0Peak-to-recent-RMS ratio. Filters background noise from transient slaps.
Rise rate0.0100.002…0.050Slope minimum.
Confirmations21…5Consecutive samples above threshold.
Warmup samples5010…100Burn-in.
HP alpha0.95constFirst-order IIR DC-block coefficient.
Target Hz50constDownsample target the adapter aims for.
Intensity floor / ceiling0.005 / 0.300constAmplitude clamping for the 0…1 published intensity.

Detection: headphone motion

CMHeadphoneMotionManager. AirPods Pro / Beats only.

SettingDefaultRangeWhat it does
Spike threshold0.10 g0.02…0.50userAcceleration magnitude required.
Crest factor1.51.0…5.0Peak-to-recent-RMS ratio.
Rise rate0.05 g/sample0.010…0.200Slope minimum.
Confirmations21…5Consecutive samples above threshold.
Warmup samples5010…100Burn-in.
Intensity floor / ceiling0.05 / 2.0 gconstMagnitude clamping for the 0…1 published intensity.

Activity sources (trackpad / mouse / keyboard)

These do not run the six-gate impact pipeline. They watch input device events directly.

SourceReactionsWhat it watchesNotes
TrackpadActivitySourcetrackpadTouching / trackpadSliding / trackpadContact / trackpadTapping / trackpadCirclingNSEvent monitor for scroll/touch + IOKit HID multitouch listenerCircling: integrates Δangle from finger position, fires when abs(circleAngleAccum) > 2π && circleEventCount >= 15.
MouseActivitySourcemouseClicked / mouseScrolledCGEvent tap on .leftMouseDown and .scrollWheelFilters out trackpad-originated events via the device-attribution gate (so an external mouse click is not also credited to the trackpad source).
KeyboardActivitySourcekeyboardTypedCGEvent tap on .keyDown, sliding rate windowCrosses the rate threshold once and publishes; debounce-gated against re-publish.

Per-event debounce gates live inside each source rather than in ReactionsConfig because the conflation patterns differ per source.

Per-source bus debounce

Pinned in ReactionsConfig. These are not user-tunable.

SourceDebounceWhy
USBSource0.05 smacOS often emits 2-3 callbacks during device spin-up.
DisplayHotplugSource0.20 smacOS emits 3-4 callbacks per real reconfiguration.
GyroscopeSource0.5 sBMI286 reports at 100 Hz; cap publish so sustained-rotation does not flood the bus.
AmbientLightDetector1.0 sCaps a flickering lamp / hand-pass-through from flooding the bus.
Audio peripheral, power, BT, Thunderbolt(none)Set-diff dedup or edge-state gating handles it.

Per-event synthesised intensity

ReactionsConfig.eventIntensity. every non-impact reaction publishes with a fixed intensity since there is no measured magnitude. Used for face selection, audio clip pick, flash opacity, LED brightness.

ReactionIntensityReactionIntensity
usbAttached0.5trackpadCircling1.0
usbDetached0.3mouseClicked0.50
acConnected0.4mouseScrolled0.40
acDisconnected0.7keyboardTyped0.35
audioPeripheralAttached0.4gyroSpike0.7
audioPeripheralDetached0.3lidOpened0.4
bluetoothConnected0.4lidClosed0.3
bluetoothDisconnected0.3lidSlammed0.95
thunderboltAttached0.5alsCovered0.7
thunderboltDetached0.3lightsOff0.5
displayConfigured0.3lightsOn0.4
willSleep0.2thermalNominal0.2
didWake0.5thermalFair0.5
trackpadTouching0.45thermalSerious0.8
trackpadSliding0.65thermalCritical1.0
trackpadContact0.40
trackpadTapping0.55

Reaction bus

SettingValueWhat it does
Per-subscriber buffer depth8bufferingNewest(8). Slow consumers drop oldest reactions rather than blocking publishers.
Enricher timeout500 msIf the enricher (audio resolve + face select) takes longer than this the bus falls back to a default envelope and publishes anyway.

LED pulse

Used by LEDFlash (Caps Lock + keyboard backlight).

SettingValueWhat it does
LED PWM frequency60 HzCaps Lock is binary; PWM-dither at 60 Hz against the shared Envelope so the user reads it as a brightness ramp.
Min pulse duration0.10 sFloor on the audio-clip-derived envelope length.
Max pulse duration1.50 sCeiling on the envelope length.
Event response duration0.6 sDefault envelope length for non-impact reactions (which carry no clip duration).

Hardware constants (BMI286)

AccelHardwareConstants. read from the IOKit HID device descriptor. Not tunable.

FieldValueWhy
HID usage page0xFF00Apple-vendor HID page.
HID usage3Accelerometer device. (Gyro = 9, ALS = 5.) Lid angle lives on a separate dedicated HID device — see the lid section above.
Required transport"SPU"Safety check. only the on-package Sensor Processing Unit qualifies.
Decimation factor2Hardware reports at 100 Hz; decimate to 50 Hz.
Magnitude min0.3 gSane lower bound for valid reads.
Magnitude max4.0 gSane upper bound.
Min report length18 bytesReject malformed HID reports.
Raw scale65 536Q15 fixed-point scaling factor in the report.
Default sample rate50 HzPost-decimation.
Sensor activity staleness500 msIf _last_event_timestamp is older than this, the runtime probe declares the sensor cold.

If you scrolled this far the joke is on both of us.

Engineered with excessive care for a deeply unnecessary purpose.