Skip to content

feat(delivery): per-identity watcher liveness in status#436

Open
Masashi-Ono0611 wants to merge 4 commits into
fujibee:mainfrom
Masashi-Ono0611:feat/monitor-status-visibility
Open

feat(delivery): per-identity watcher liveness in status#436
Masashi-Ono0611 wants to merge 4 commits into
fujibee:mainfrom
Masashi-Ono0611:feat/monitor-status-visibility

Conversation

@Masashi-Ono0611

@Masashi-Ono0611 Masashi-Ono0611 commented Jul 19, 2026

Copy link
Copy Markdown

Summary

Extends delivery.sh status so monitor-tool agent types (watch.sh receive path) report per-identity receiver liveness at the same granularity as the existing Codex bridge lines.

  • Exclusive (actas) receivers: ready sentinel + watch.<token>.pid (the watcher process, not the agent CLI pid embedded in composite instance ids) + cmdline match
  • Broad watchers (e.g. Claude Code SessionStart default, no ACTIVE_NAME): no per-identity ready file — report no exclusive receiver (broad watcher alive, pid N) instead of a false not running
  • Aggregate watch processes: N alive, M stale line kept; Codex plug unchanged

Example output

mode: monitor
Watcher: masa-dev/masa-grok alive (exclusive, pid 12345)
Watcher: masa-dev/masa-claude no exclusive receiver (broad watcher alive, pid 67890)
watch processes: 2 alive, 0 stale pidfiles

Credits / related

Test plan

  • bats tests/test_delivery.bats -f 'delivery status' — green (includes exclusive alive, agent-alive/watcher-dead false-alive guard, broad coverage, not running)
  • New receiver-live.sh direct cases for missing ready / agent-only composite
  • CI bats on this PR

Notes

  • CHANGELOG intentionally not updated (caller preference for PR-time decision).
  • Ready-file semantics unchanged (still actas-only); broad watchers are detected via scoped live watch.sh pidfiles, not by writing ready files for them.

Update (2026-07-19): additional review pass, three more fixes

A follow-up /review:self-multi-model pass (Codex + Fugu, independently
converging on two of these) found real gaps before this had any maintainer
eyes on it, now fixed in the latest commit:

  • P1 — broad-watcher false positive: the broad-watcher scan matched any
    watch.sh cmdline containing " <project> <type> " as a substring. An
    EXCLUSIVE watcher's argv (watch.sh <sid> <project> <type> <agent>) also
    contains that substring, so it could misreport an exclusive watcher for a
    DIFFERENT agent as "broad coverage" for an identity that actually has zero
    receivers. Now requires project/type to be the trailing tokens (nothing
    after them), true only for a genuinely broad invocation.
  • P1 — ps-unavailable false negative: in Claude Code sandboxes where
    ps is unavailable, compat_get_cmdline returns empty, so both the
    broad-watcher scan's and receiver-live.sh's mandatory argv checks
    rejected every live watcher — reporting "not running" even though
    watch.sh's own self-clean logic already has a documented fallback for
    exactly this environment. Both now skip argv validation and trust
    kill -0 alone when cmdline can't be inspected (the broad-watcher scan
    falls back to "the sole live watcher, if unambiguous," since it can't
    disambiguate across multiple untyped candidates without argv).
  • P2 — pid-recycling defense too weak: receiver-live.sh only checked
    that a live pid's cmdline generically looked like watch.sh, not that it
    was watch.sh for THIS agent — a recycled pid landing on an unrelated
    watcher (different team/role) could false-alive. Now also requires the
    agent name as a trailing argument.

New regression tests added for all three (tests/test_delivery.bats,
including a mocked-ps-failure harness reused from the existing pattern in
test_team.bats). Full suite re-verified: 737/737 (this worktree's copy of
the pre-existing install: watch.sh self-cleans... flake did not reproduce
on this run).

Extend delivery.sh status for monitor-tool types (watch.sh ready-file
path) so each registered identity reports alive/not-running with the
same granularity as Codex bridge lines. Keeps the aggregate watch
count for non-actas watchers; codex plug unchanged.
Rebuild monitor-tool watcher liveness in delivery.sh status on the
shared ready-sentinel primitive from fujibee#372 (@u-ichi):

- add scripts/receiver-live.sh (credit fujibee#372; composite instance-id
  fallback for today's watch.sh ready tokens plus optional --pid)
- delivery status prints "Watcher: team/agent alive|not running"
  by calling receiver-live.sh per registered identity
- codex bridge status path unchanged; aggregate watch count kept

Tests cover composite tokens, explicit pid= form, missing/dead ready,
and shared use from claude-code identities.
Address card-3 P1s from multi-model review:

- receiver-live.sh probes watch.<token>.pid (the watcher), not the agent
  pid embedded in composite ready tokens, so a live agent with a dead
  watcher is no longer false-alive
- delivery status falls back to scoped broad-watcher detection when an
  identity has no exclusive ready file (Claude Code SessionStart path),
  printing "no exclusive receiver (broad watcher alive, pid N)" instead
  of a hard not-running

Credits fujibee#372 (@u-ichi) for the ready-path primitive.
…e no-ps

Two P1s found by /review:self-multi-model (Codex + Fugu, independently
converging on both), plus one P2 (Codex):

- agmsg_delivery_find_broad_watcher_pid matched any watch.sh cmdline
  containing " <project> <type> " as a substring. An EXCLUSIVE watcher's
  argv (watch.sh <sid> <project> <type> <agent>) also contains that
  substring, so it could be misreported as "broad watcher coverage" for a
  completely different agent that actually has zero receivers. Now requires
  project/type to be the TRAILING tokens (no agent arg after them), which is
  true only for a genuinely broad invocation.

- In Claude Code sandboxes where `ps` is unavailable, compat_get_cmdline
  returns empty, so both this function's and receiver-live.sh's mandatory
  argv checks rejected every live watcher — reporting "not running" even
  though watch.sh's own self-clean logic already has a documented fallback
  for exactly this environment. Both now skip argv validation and trust
  kill -0 alone when cmdline can't be inspected (falling back to "the sole
  live watcher, if unambiguous" for the broad-watcher scan, since it can't
  disambiguate across multiple untyped candidates without argv).

- receiver-live.sh's pid-recycling defense only checked that the live pid's
  cmdline generically looked like watch.sh, not that it was watch.sh FOR
  THIS agent — a recycled pid landing on an unrelated watcher (different
  team/role) could false-alive. Now also requires the agent name as a
  trailing argument.
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