When building autonomous AI systems, developers eventually hit a fundamental architectural wall. Your coding agent asks you a question, and you step away from the keyboard. Today, nothing happens. The session hangs, the question rots, and the work stalls.
At J. Servo LLC, we architect enterprise AI systems to operate predictably. We built Sundial to act as the missing half of the human-in-the-loop framework[cite: 1]. It operates on a single defining principle: Sundial measures absence, not time[cite: 1].
When the human becomes the blocker, the agent's clock keeps running[cite: 1]. It nudges you on your desktop, escalates politely through your absence, and greets you with continuity upon your return[cite: 1]. If you never answer, the agent proceeds on its stated judgment or stands down[cite: 1]. It does this deterministically, with zero model calls, and runs 100% locally[cite: 1].
Relying on a Large Language Model to determine if a user has abandoned a session violates lean architecture principles. Time tracking belongs at the system level. The separation of actors is the design[cite: 2].
Sundial enforces a strict architectural boundary across three main components:
HIDIdleTime
, lsappinfo
, and pmset
on macOS, and xprintidle
or loginctl
on Linux[cite: 1]. Any missing sensor returns None
and softens to wall time rather than blocking the system[cite: 1].launchd
that handles presence classification and escalation[cite: 1, 2]. It uses zero LLMs[cite: 2].data/
directory[cite: 2]. State is written atomically using NamedTemporaryFile
, fsync()
, and os.replace()
, serialized by inter-process locking via fcntl.flock
[cite: 1]. Escalation advances only while you genuinely have not seen the chat[cite: 1]. Sundial categorizes your presence into three strict states:
The system enforces urgency tiers[cite: 1]. A high-urgency task utilizes a retimed ladder of 5, 10, and 20 minutes, backed by a hard 40-minute wall ceiling that forces a final resolution regardless of sensor data[cite: 1].
A ripe nudge never fires mid-keystroke[cite: 1]. Drawing from Interruption Science, the daemon holds ripe notifications for up to three minutes waiting for a natural typing gap or application switch before delivering[cite: 1].
Sound courtesy is strictly enforced. Chimes escalate with urgency, but they mute unconditionally if your screen is locked or if you have been away for more than 30 minutes[cite: 1].
Agents must stop guessing execution durations using fabricated calendar weeks[cite: 1]. Sundial tracks the empirical ratio distribution of actual versus estimated time across completed tasks[cite: 1].
The estimation engine (lib/estimator.py
) operates purely mathematically to compute empirical P50 and P90 execution durations[cite: 1]. It applies a small-n honesty floor, utilizing a 2.0x multiplier when sample sizes are below five, ensuring the system never provides confident numbers from thin data[cite: 1, 2].
The trigger path never thinks[cite: 2]. When an agent blocks on an awaiting-reply
question, the ladder climbs until expiry, triggering the Autonomy Gate in lib/policy.py
[cite: 1].
The agent is forced into a deterministic verdict:
The absolute autonomy rule: Silence-while-present is an answer, whereas silence-while-absent is a void[cite: 1]. They receive distinct, deterministic responses[cite: 1].
Sundial integrates via a generic hook protocol passing JSON on stdin
and outputting text blocks to stdout
[cite: 1]. It supports ready-made adapters for claude-code
, hermes
, and generic environments[cite: 1].
bash
git clone [https://github.com/bigjoe-oti/sundial.git](https://github.com/bigjoe-oti/sundial.git) ~/sundial
cd ~/sundial
./setup.sh --name "YourName" --fresh
Built with obsession by Yousef Ali and the engineering team at J. Servo LLC.