Skip to content

Feature: pluggable out-of-band notifier (push) for captain-relevant wakes #106

Description

@cjunxiang

Summary

The detection side of "firstmate misses wakes between turns" is solved: #26 (watcher crash) and #27 (durable wake queue) ensure every captain-relevant wake is captured losslessly and drained at the start of the next supervisor turn. The delivery side is still session-bound: firstmate only relays a wake to the captain inside an active supervisor turn. When the captain is away or the supervisor session is idle, done / needs-decision / blocked / failed events sit correctly in the durable queue — but nothing pushes them to the captain out-of-band.

This proposes an opt-in, pluggable wake-hook that delivers captain-relevant events to an external channel independent of supervisor-session liveness — closing the delivery half of Section 9 ("reaches the captain immediately") in agents.md and complementing /afk.

Observed gap

Hit this directly: during a quiet stretch the supervisor's watcher lapsed and ~3h of captain-relevant events (a finished audit; a task blocked on a decision) sat in the wake queue, surfaced only on a manual "how's it going?" poke. Nothing was lost (#27's durable queue worked), but nothing reached the captain until they returned to the terminal. This is the exact symptom #27's author described ("finished work goes unrelayed… until something pokes the supervisor") — #27 fixed capture; this addresses the out-of-band reach.

Why it fits firstmate

  • Section 9 in agents.md contract is "reaches the captain immediately." Today that's only honored inside an active session. A push channel honors it when the session is idle.
  • firstmate already treats "captain is away" as first-class (/afk, the away-mode daemon). An away captain currently has no channel to hear firstmate at all — push is the natural complement.
  • Delivery is orthogonal to detection (which Daemon-mode watcher (or durable wake queue) — supervisor misses crewmate wakes between turns in chat mode #27 solved), so this is a pure addition to the delivery layer — it touches none of the wake-capture logic.
  • It matches the project's pluggable/opt-in philosophy (harness-adapters, delivery modes, yolo). The contribution is a generic wake-hook extension point + adapter contract, not a vendor-specific feature.

Proposed shape (Phase 1, outbound-only)

  • A tiny, opt-in, fire-and-forget hook in fm-watch.sh's signal path — engineered so a notifier failure can never stall supervision (guarded, error-isolated, with a test asserting the watcher still wakes when the hook errors).
  • A notifier core that filters to the four captain-actionable states (done / needs-decision / blocked / failed — never working, never heartbeats) and dedupes (notify-once per event).
  • A reference Telegram adapter (curl sendMessage) under contrib/notifiers/, resolved like harness-adapters from a gitignored config/notify. No config ⇒ feature inert (zero behavior change for existing users).
  • Docs: an AGENTS.md subsection + a setup skill; tests for the dedupe/state-filter logic.

Scope / phasing

  • Phase 1 (this proposal): outbound-only, Telegram reference adapter, default-off.
  • Phase 2 (follow-up): extract the pluggable interface + a second adapter (e.g. macOS osascript, generic webhook) to prove portability.
  • Phase 3 (deferred, separate): two-way (reply from phone → firstmate action). Needs a public endpoint + inbound security — a bigger feature, explicitly out of scope here.

Non-goals

Open questions for discussion

  1. Pluggable adapter contract vs a single built-in channel — I'd strongly recommend pluggable; happy to defer to maintainer preference.
  2. Default payload — minimal (<task>: <state> + repo), with full PR URL opt-in (privacy: task content leaves the machine).
  3. Relationship to /afk — push in addition to the in-session injection, or push-only while away?
  4. Where the adapter lives — contrib/notifiers/ (reinforces "adapter, not core") vs alongside core.

Willingness to implement

Happy to implement Phase 1 as a PR if there's interest. Scoped to ~6 small files (hook + notifier core + adapter + resolver + config template + skill) plus tests and docs, default-off and opt-in.

Also happy to run through any other viable designs before we do anything. potentially we could also introduce in a similar manner to claude code's /hook. Possibility is vast, up to maintainers 😄

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions