Skip to content

fix: keep idle watcher supervision silent - #10

Merged
kunchenguid merged 2 commits into
mainfrom
fm/watcher-silence
Jun 12, 2026
Merged

kunchenguid merged 2 commits into
mainfrom
fm/watcher-silence

Conversation

@kunchenguid

Copy link
Copy Markdown
Owner

Intent

The captain asked me to update firstmate's own instructions so future supervision through bin/fm-watch.sh does not waste user-facing turns with idle status messages. The change should clarify that waiting on the watcher is intentionally silent, empty polls and elapsed waiting time are internal tool bookkeeping, unchanged heartbeat reviews should not be reported, and watcher mechanics such as restart/poll/no-change confirmations do not reach the captain unless they reveal a captain-relevant issue.

What Changed

  • Clarifies firstmate supervision instructions so waiting on bin/fm-watch.sh, empty polls, elapsed waiting time, and no-change heartbeat reviews remain internal instead of user-facing updates.
  • Updates the README and watcher script wording to describe fm-watch.sh as waking when supervision work is due, including heartbeat reviews, not only when a crewmate needs attention.
  • Documents that routine watcher mechanics such as polling, restarting, and confirming no status changed should not reach the captain unless they surface a relevant issue.

Risk Assessment

✅ Low: The change only clarifies documentation for watcher communication behavior and does not alter executable code or operational mechanics.

Testing

I verified the documentation-only behavior change by inspecting the changed AGENTS.md supervision flow and producing an evidence transcript showing every intended watcher-silence rule present; no source tests were applicable, and the working tree remained clean.

Evidence: Watcher-silence instruction evidence

309:Waiting on the watcher is intentionally silent. 310:After starting or restarting it, do not send idle progress updates to the captain; wait until it returns signal, stale, check, or heartbeat, unless the captain asks for status. 311:Empty polls, elapsed waiting time, and "still no change" are tool bookkeeping, not conversational progress. 324: A heartbeat with no captain-relevant change is internal; do not report that the fleet is unchanged. 344:Silence is the correct state while a healthy background watcher is waiting. 366:Routine watcher mechanics include restarting the watcher, polling a waiting watcher, and confirming that no status changed.

Changed watcher-silence instructions in AGENTS.md:

309:Waiting on the watcher is intentionally silent.
310:After starting or restarting it, do not send idle progress updates to the captain; wait until it returns `signal`, `stale`, `check`, or `heartbeat`, unless the captain asks for status.
311:Empty polls, elapsed waiting time, and "still no change" are tool bookkeeping, not conversational progress.
324:   A heartbeat with no captain-relevant change is internal; do not report that the fleet is unchanged.
344:Silence is the correct state while a healthy background watcher is waiting.
366:Routine watcher mechanics include restarting the watcher, polling a waiting watcher, and confirming that no status changed.

Pipeline

Updates from git push no-mistakes

✅ **intent** - passed

✅ No issues found.

✅ **Rebase** - passed

✅ No issues found.

✅ **Review** - passed

✅ No issues found.

✅ **Test** - passed

✅ No issues found.

  • Reviewed git diff f3958097383870fbc9be46365016a5252a73beff..HEAD -- AGENTS.md to confirm the change scope is limited to watcher-silence instructions.
  • Read AGENTS.md section 8 and section 9 around lines 304-366 to evaluate the end-user supervision instructions in context.
  • Ran rg -n 'Waiting on the watcher|idle progress|Empty polls|heartbeat.*captain-relevant|Silence is the correct state|Routine watcher mechanics' AGENTS.md and saved the matching instruction lines as evidence.
  • Ran git status --short after testing to confirm no working-tree artifacts were created.
✅ **Document** - passed

✅ No issues found.

✅ **Lint** - passed

✅ No issues found.

✅ **Push** - passed

✅ No issues found.

@kunchenguid
kunchenguid merged commit a5ffb9f into main Jun 12, 2026
3 checks passed
@kunchenguid
kunchenguid deleted the fm/watcher-silence branch June 12, 2026 22:26
@OCPdev25

OCPdev25 commented Jul 6, 2026

Copy link
Copy Markdown

Superseded by pipeline PR.

vipentti pushed a commit to vipentti/firstmate that referenced this pull request Aug 5, 2026
* Clarify watcher silence protocol

* no-mistakes(document): Sync watcher silence documentation
@ki-za

ki-za commented Aug 29, 2026

Copy link
Copy Markdown

Scout plan (huddle-app second mate, 2026-08-29)

Proposed Options / Plan / Blocking / Lead decisions for this ticket, from the ha-input-plan scout report.

Current state

  • app/src/lib/huddle/ReplyForm.svelte:51-65 has the composer textarea and forwards each native input change. app/src/lib/huddle/view-state.ts:64-65 retains that exact draft text.
  • [V] VOICE is wired at ReplyForm.svelte:104-112, but showVoicePlaceholder() at lines 39-41 only shows “FluidVoice wiring arrives with the status-bar host.” App.svelte:279-281 routes the keyboard shortcut to that control.
  • App.svelte:117-125 posts the composer text as normal markdown content; docs/contract.md:97-108 and schema/message.v1.json:39-50 already preserve that text exactly. There is no audio record, transcription route, or recording API.
  • The Hammerspoon proposal creates the webview and its existing Huddle hotkey (host/hammerspoon/huddle.lua:136-168), but exposes no app-to-host message port and no FluidVoice configuration. docs/host.md:43-61 fixes the machine-change boundary as a nix-dots patch applied by the captain.

Missing: the host bridge that invokes the installed FluidVoice hotkey while the focused composer receives its normal inserted text.

Options

The recorded default is fixed: invoke the installed FluidVoice hotkey and let its inserted text become the composer draft. In-app recording and transcription remain later work; they add a recording, service, quota, and cost boundary.

Recommended Plan

Modules:

  • app/src/lib/huddle/ReplyForm.svelte owns the Voice control’s host request and the browser explanation when the host capability is absent. It keeps the textarea and native input path unchanged.
  • app/src/App.svelte keeps [V] routed to that one control. app/src/lib/huddle/view-state.ts remains the sole draft owner.
  • host/hammerspoon/huddle.lua owns a WebKit user-content message port, validates a single FluidVoice request, and sends the configured global FluidVoice hotkey without taking focus from the webview.
  • docs/host.md documents the capability, browser behavior, configuration, and smoke. Add a new proposed only docs/proposals/2026-08-29-hammerspoon-fluidvoice.patch against nix-dots. It updates the proposed Hammerspoon module and init.lua; it is never applied from this repository.

Seams:

  • The Huddle app requests the host through the injected WebKit message port. It imports no Hammerspoon API. The browser has no host capability and reports that Voice requires the Hammerspoon host.
  • The host exposes one fluidVoiceHotkey configuration value and invokes that installed global hotkey. It does not record, transcribe, read the clipboard, or post a message.
  • FluidVoice inserts text into the already focused textarea. The existing input handler moves that text into the draft; ordinary Reply posts it through the existing content.text path. No docs/contract.md route or schema/ field changes.
  • The host change is carried only as the proposed nix-dots patch and its exact apply procedure, following docs/proposals/README.md.

Validation criteria:

  • In a browser, [V] leaves the composer usable and states that the Hammerspoon host is required; no recording permission or network request occurs.
  • In the proposed Hammerspoon host, open a reply, press [V], speak a fixed short sentence, and confirm the resulting text appears once in the focused composer. Reply and verify the ledger’s content.text equals that sentence exactly.
  • Repeat with the composer closed and with the host offline; each path gives an actionable local status and creates no record.
  • Capture one overlay picture showing the populated composer, and retain the matching ledger line in the dated smoke note. Confirm the host still hides/shows its one webview and its existing hotkey remains intact.

Blocking?

blocked by lead decision — the proposed nix-dots patch needs the captain’s actual installed FluidVoice shortcut; the recorded input-path default itself is not reopened.

Lead decisions

  • Use a configured fluidVoiceHotkey rather than a fixed shortcut? — Yes (recommended). The captain supplies the installed modifiers and key in the proposed nix-dots patch.

NewAiCoder referenced this pull request in NewAiCoder/firstmate Sep 26, 2026
)

* feat(spawn): minimal worker tool surface with brief-declared extras

Crewmates and scouts now launch with --strict-mcp-config, an empty
per-task --mcp-config, and --setting-sources project,local, dropping
the plugin skill catalog that was most of a 135k-145k token cold
prefix re-read across an average of 280 turns per seat (spec D6,
docs/superpowers/specs/2026-09-05-token-telemetry-design.md).

bin/fm-dod-lib.sh's fm_brief_tools reads the brief's ## Firstmate spec
tools: line and drops anything not in browser/context7/mockup/lavish/
none with a warning, so a typo narrows the surface instead of widening
it. bin/fm-spawn.sh writes the resolved MCP config into the task tmp
dir at 0600 and wires it into the claude launch template.

fm-brief.sh scaffolds tools: none into every new brief. That appends
a fixed line after the {FIRSTMATE_SPEC} placeholder, so
fm_brief_task_placeholders_present also had to recognize the new
unfilled-scaffold shape alongside the legacy bare placeholder, or an
unfilled brief would have spawned as though it were filled.

Also updates tests/fm-spawn-dispatch-profile.test.sh and
tests/fm-secondmate-harness.test.sh, whose assertions pinned the
exact claude launch string, for the new flags.

Out of scope for this repo: the no-mistakes pipeline-seat config
template and the before/after cold-prefix measurement both live in
the operator's private config repo, a separate repo from this worktree.

* no-mistakes(review): mirror captain's user-scope hooks and exempt secondmate from minimal claude surface

* no-mistakes(lint): Fix SC2015 A&&B||C guard shape in fm-spawn-tool-surface test

---------

Co-authored-by: NewAiCoder <170579485+NewAiCoder@users.noreply.github.com>
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.

3 participants