Skip to content

Auto-focus (timed + calls), config.env hardening, CI/tests, focus-mute bugfix - #1

Merged
QuintinAdam merged 5 commits into
mainfrom
improvements-focus-and-hardening
Jul 16, 2026
Merged

QuintinAdam merged 5 commits into
mainfrom
improvements-focus-and-hardening

Conversation

@QuintinAdam

Copy link
Copy Markdown
Owner

Summary

Three improvements plus a bug fix found by the new tests.

Auto-focus (serves the "meeting / music" use case)

  • Timed focus — agent-notify off 30m (also 1h/90s) mutes then auto-unmutes; menu bar has a Focus for… submenu (15/30/60 min) with a live countdown; the icon self-restores on expiry. New muted_until epoch in state.
  • Auto-mute in calls — the menu-bar app detects a live mic (CoreAudio via ctypes, no extra deps) and writes a freshness-stamped sentinel the hook obeys (<60s, so a dead app never leaves you stuck muted). Toggle: autocall on|off / menu item (default on). DND omitted — not reliably readable on macOS 26+.

Hardening

  • Secrets out of settings.json — the hook now sources ~/.config/agent-notify/config.env (mode 600) for AGENT_NOTIFY_* vars, the right home for the chat webhook. Adds config.env.example, installer seeding, and rotation guidance.
  • CI + tests — tests/run.sh (CLI, hook mute-gating via new AGENT_NOTIFY_DRY=1, and the register/unregister jq filters, now shared in lib/register.sh). GitHub Actions: shellcheck + py_compile on Linux, smoke tests on macOS.

Bug fix (caught by the new tests)

The hook read booleans with .key // empty, but jq's // treats false as empty — so enabled/banner/chat/japanese: false were silently dropped and focus mode wasn't actually muting. Now read via has() + tostring.

Test plan

  • bash tests/run.sh — all pass (CLI, hook gating incl. focus/timed/call, register idempotency).
  • shellcheck --severity=warning clean; install.sh --dry-run verified.

The chat webhook is a 'whoever-has-it-can-post' secret; settings.json is easy to
sync/share/screenshot. The hook now sources ~/.config/agent-notify/config.env (a
mode-600 shell file) for AGENT_NOTIFY_* vars. Adds config.env.example, installer
seeding, gitignore, and doc guidance to rotate exposed webhooks.
New muted_until epoch in state forces speech off until it passes, independent of
the manual enabled flag. CLI: `agent-notify off 30m|1h|90s`; status shows the
countdown. Menu bar: 'Focus for…' submenu (15/30/60 min) + Cancel timer, live
countdown in the Focus item, icon self-restores on expiry. Hook honors the window.
The menu-bar app detects the default input device running (CoreAudio via ctypes,
no extra deps) and writes a freshness-stamped sentinel; the hook suppresses speech
while it's fresh (<60s), so a dead app never leaves you stuck muted. Toggle with the
'Auto-mute in calls' menu item or `agent-notify autocall on|off` (default on). DND
detection omitted — not reliably readable on macOS 26+.
Fix: the hook read booleans with `.key // empty`, but jq's // treats false as
empty — so enabled/banner/chat/japanese=false were silently dropped and focus mode
never actually muted. Now read via has()+tostring. Caught by the new tests.

Also: extract the settings.json register/unregister jq into lib/register.sh (shared
by install/uninstall/tests), add tests/run.sh (CLI + hook gating via AGENT_NOTIFY_DRY
+ register idempotency), a GitHub Actions workflow (shellcheck + py_compile on Linux,
smoke tests on macOS), a CI badge, and a Development section.
An older state.json (predating muted_until/auto_call) made `get`/status report a
missing key as its falsy value (e.g. 'auto-call: off' when the effective default is
on). ensure() now merges defaults into an existing file (existing values win),
rewriting only when something was missing.
@QuintinAdam
QuintinAdam marked this pull request as ready for review July 16, 2026 09:20
@QuintinAdam
QuintinAdam merged commit cf49a1c into main Jul 16, 2026
4 checks passed
@QuintinAdam
QuintinAdam deleted the improvements-focus-and-hardening branch July 16, 2026 09:20
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant