Skip to content

comms mute: a member can silence their own wake without leaving the group chat - #4780

Merged
trissim merged 1 commit into
mainfrom
claude-laptop/comms-mute
Nov 15, 2026
Merged

trissim merged 1 commit into
mainfrom
claude-laptop/comms-mute

Conversation

@trissim

@trissim trissim commented Nov 15, 2026

Copy link
Copy Markdown
Contributor

What

Wake-all stays the law. #3478 is untouched: every #comms post still pings every member to triage it. On top of that a member can now go heads-down for a while — they keep receiving every message, they are just not woken to triage it until the mute expires.

Mechanism (one pure input, one small store)

  • NoWakeReason.MUTED + resolve_wake_cohort(..., muted: frozenset[ThreadLookup]). A muted recipient gets NoWakeDecision(MUTED) instead of a triage/full wake — the same early-return shape as the existing non-conversation guard right above it. Still a frozen recipient (delivery unchanged); the committed decision round-trips through the wire like any other.
  • MuteLedger (mutes.json) — a durable single-file store: set / muted(now) / clear. Expiry is a until > now compare, no sweeper. publisher.InitialWrites reads it once at publish and passes the active set; an absent file is simply no mutes, so every existing publish is byte-identical when nobody is muted.
  • agent-comms mute --from NAME --minutes N (and --clear) — self-mute, auto-discovered in the cli_verbs ModuleMembers package (no manifest edit).

Self-mute silences even an @mention of you — that is the point of going heads-down. Muting one specific sender (not all) is the clean follow-on: the same Mute record plus a scope member, deliberately not shipped half-done here.

Evidence

  • tests/test_wake.py: muted member delivered-without-wake while others still triage; mute overrides an @mention; empty mute set leaves wake-all untouched; MUTED row round-trips through the wire.
  • tests/test_mute_ledger.py: set / expire-by-time / replace-not-duplicate / clear.
  • 28 passed. Focused publish/wake batch (channel + coordination + route + cli) running green on top.

🤖 Generated with Claude Code

https://claude.ai/code/session_01XbFMSnLEc51gw21bLFFRK1

…roup chat

Wake-all stays the default (#3478): every channel post still pings every member.
A member may now opt their own wake out for a bounded time -- they still RECEIVE
every message, only the triage wake is dropped -- via a small durable mute ledger
read once at publish.

- NoWakeReason.MUTED; resolve_wake_cohort takes a pure `muted` lookup set and a
  muted recipient gets NoWakeDecision(MUTED) instead of a triage/full wake, the
  same early-return shape as the existing non-conversation guard. The committed
  decision round-trips through the wire unchanged.
- MuteLedger (mutes.json): set / active-by-time / clear; expiry is a timestamp
  compare, no sweeper. publisher.InitialWrites reads it at publish and passes the
  active set; an absent file is no mutes.
- `agent-comms mute --from NAME --minutes N` / `--clear`: self-mute, auto-discovered
  in the cli_verbs ModuleMembers package.

Self-mute silences even an @mention of you -- the point of going heads-down.
Muting one specific sender (not all) is the clean follow-on: the same record plus
a scope member, not shipped half-done here.

tests: test_wake (muted cohort, mention override, wire round-trip), test_mute_ledger
(set/expire/replace/clear). 28 passed.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01XbFMSnLEc51gw21bLFFRK1
@trissim
trissim merged commit 21ff333 into main Nov 15, 2026
1 of 3 checks passed
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